1 //
2 // Copyright 2020 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 #ifndef GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_EXTERNAL_ACCOUNT_CREDENTIALS_H
18 #define GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_EXTERNAL_ACCOUNT_CREDENTIALS_H
19 
20 #include <grpc/support/port_platform.h>
21 
22 #include <functional>
23 #include <string>
24 #include <vector>
25 
26 #include "absl/strings/string_view.h"
27 
28 #include "src/core/lib/gprpp/orphanable.h"
29 #include "src/core/lib/gprpp/ref_counted_ptr.h"
30 #include "src/core/lib/gprpp/time.h"
31 #include "src/core/lib/http/httpcli.h"
32 #include "src/core/lib/http/parser.h"
33 #include "src/core/lib/iomgr/closure.h"
34 #include "src/core/lib/iomgr/error.h"
35 #include "src/core/lib/iomgr/polling_entity.h"
36 #include "src/core/lib/json/json.h"
37 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
38 
39 namespace grpc_core {
40 
41 // Base external account credentials. The base class implements common logic for
42 // exchanging external account credentials for GCP access token to authorize
43 // requests to GCP APIs. The specific logic of retrieving subject token is
44 // implemented in subclasses.
45 class ExternalAccountCredentials
46     : public grpc_oauth2_token_fetcher_credentials {
47  public:
48   // External account credentials json interface.
49   struct Options {
50     std::string type;
51     std::string audience;
52     std::string subject_token_type;
53     std::string service_account_impersonation_url;
54     std::string token_url;
55     std::string token_info_url;
56     Json credential_source;
57     std::string quota_project_id;
58     std::string client_id;
59     std::string client_secret;
60     std::string workforce_pool_user_project;
61   };
62 
63   static RefCountedPtr<ExternalAccountCredentials> Create(
64       const Json& json, std::vector<std::string> scopes,
65       grpc_error_handle* error);
66 
67   ExternalAccountCredentials(Options options, std::vector<std::string> scopes);
68   ~ExternalAccountCredentials() override;
69   std::string debug_string() override;
70 
71  protected:
72   // This is a helper struct to pass information between multiple callback based
73   // asynchronous calls.
74   struct HTTPRequestContext {
HTTPRequestContextHTTPRequestContext75     HTTPRequestContext(grpc_polling_entity* pollent, Timestamp deadline)
76         : pollent(pollent), deadline(deadline) {}
~HTTPRequestContextHTTPRequestContext77     ~HTTPRequestContext() { grpc_http_response_destroy(&response); }
78 
79     // Contextual parameters passed from
80     // grpc_oauth2_token_fetcher_credentials::fetch_oauth2().
81     grpc_polling_entity* pollent;
82     Timestamp deadline;
83 
84     // Reusable token fetch http response and closure.
85     grpc_closure closure;
86     grpc_http_response response;
87   };
88 
89   // Subclasses of base external account credentials need to override this
90   // method to implement the specific subject token retrieval logic.
91   // Once the subject token is ready, subclasses need to invoke
92   // the callback function (cb) to pass the subject token (or error)
93   // back.
94   virtual void RetrieveSubjectToken(
95       HTTPRequestContext* ctx, const Options& options,
96       std::function<void(std::string, grpc_error_handle)> cb) = 0;
97 
98  private:
99   // This method implements the common token fetch logic and it will be called
100   // when grpc_oauth2_token_fetcher_credentials request a new access token.
101   void fetch_oauth2(grpc_credentials_metadata_request* req,
102                     grpc_polling_entity* pollent, grpc_iomgr_cb_func cb,
103                     Timestamp deadline) override;
104 
105   void OnRetrieveSubjectTokenInternal(absl::string_view subject_token,
106                                       grpc_error_handle error);
107 
108   void ExchangeToken(absl::string_view subject_token);
109   static void OnExchangeToken(void* arg, grpc_error_handle error);
110   void OnExchangeTokenInternal(grpc_error_handle error);
111 
112   void ImpersenateServiceAccount();
113   static void OnImpersenateServiceAccount(void* arg, grpc_error_handle error);
114   void OnImpersenateServiceAccountInternal(grpc_error_handle error);
115 
116   void FinishTokenFetch(grpc_error_handle error);
117 
118   Options options_;
119   std::vector<std::string> scopes_;
120 
121   OrphanablePtr<HttpRequest> http_request_;
122   HTTPRequestContext* ctx_ = nullptr;
123   grpc_credentials_metadata_request* metadata_req_ = nullptr;
124   grpc_iomgr_cb_func response_cb_ = nullptr;
125 };
126 
127 }  // namespace grpc_core
128 
129 #endif  // GRPC_SRC_CORE_LIB_SECURITY_CREDENTIALS_EXTERNAL_EXTERNAL_ACCOUNT_CREDENTIALS_H
130