1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #pragma once
7 
8 #include <aws/core/Core_EXPORTS.h>
9 #include <aws/core/utils/memory/AWSMemory.h>
10 #include <aws/core/utils/memory/stl/AWSString.h>
11 #include <aws/core/client/ClientConfiguration.h>
12 #include <aws/core/client/AWSErrorMarshaller.h>
13 #include <aws/core/auth/AWSCredentials.h>
14 #include <aws/core/AmazonWebServiceResult.h>
15 #include <aws/core/utils/DateTime.h>
16 #include <memory>
17 #include <mutex>
18 namespace Aws
19 {
20     namespace Http
21     {
22         class HttpClient;
23         class HttpRequest;
24         enum class HttpResponseCode;
25     } // namespace Http
26 
27     namespace Internal
28     {
29         /**
30          * Simple client for accessing the AWS remote data by Http.
31          * Currently we use it to access EC2 Metadata and ECS Credential.
32          */
33         class AWS_CORE_API AWSHttpResourceClient
34         {
35         public:
36             /**
37              * Builds an AWSHttpResourceClient instance by using default http stack.
38              */
39             AWSHttpResourceClient(const char* logtag = "AWSHttpResourceClient");
40             AWSHttpResourceClient(const Client::ClientConfiguration& clientConfiguration, const char* logtag = "AWSHttpResourceClient");
41 
42             AWSHttpResourceClient& operator =(const AWSHttpResourceClient& rhs) = delete;
43             AWSHttpResourceClient(const AWSHttpResourceClient& rhs) = delete;
44             AWSHttpResourceClient& operator =(const AWSHttpResourceClient&& rhs) = delete;
45             AWSHttpResourceClient(const AWSHttpResourceClient&& rhs) = delete;
46 
47             virtual ~AWSHttpResourceClient();
48 
49             /**
50              * Connects to an HTTP endpoint to read the specified resource and returns the text contents.
51              * The resource URI = endpoint + resourcePath (e.g:http://domain/path/to/res)
52              * @param endpoint The HTTP resource to connect to.
53              * @param resourcePath A path appended to the endpoint to form the final URI.
54              * @param authToken An optional authorization token that will be passed as the value of the HTTP
55              * header 'Authorization'.
56              * @return The response from the HTTP endpoint as a string.
57              */
58             virtual Aws::String GetResource(const char* endpoint, const char* resourcePath, const char* authToken) const;
59 
60             /**
61              * Connects to an HTTP endpoint to read the specified resource and returns the text contents.
62              * The resource URI = endpoint + resourcePath (e.g:http://domain/path/to/res)
63              * @param endpoint The HTTP resource to connect to.
64              * @param resourcePath A path appended to the endpoint to form the final URI.
65              * @param authToken An optional authorization token that will be passed as the value of the HTTP
66              * header 'Authorization'.
67              * @return The response from the HTTP endpoint as a string, together with the http response code.
68              */
69             virtual AmazonWebServiceResult<Aws::String> GetResourceWithAWSWebServiceResult(const char *endpoint, const char *resourcePath, const char *authToken) const;
70 
71             /**
72              * Above Function: Aws::String GetResource(const char* endpoint, const char* resourcePath, const char* authToken) const;
73              * is limited to HTTP GET method and caller can't add wanted HTTP headers as well.
74              * This overload gives caller the flexibility to manipulate the request, as well returns the HttpResponseCode of the last attempt.
75              */
76             virtual AmazonWebServiceResult<Aws::String> GetResourceWithAWSWebServiceResult(const std::shared_ptr<Http::HttpRequest> &httpRequest) const;
77 
78             /**
79              * Set an error marshaller so as to marshall error type from http response body if any.
80              * So that it can work with retry strategy to decide if a request should retry or not.
81              */
SetErrorMarshaller(Aws::UniquePtr<Client::AWSErrorMarshaller> errorMarshaller)82             void SetErrorMarshaller(Aws::UniquePtr<Client::AWSErrorMarshaller> errorMarshaller) { m_errorMarshaller = std::move(errorMarshaller); }
GetErrorMarshaller()83             const Client::AWSErrorMarshaller* GetErrorMarshaller() const { return m_errorMarshaller.get(); }
84 
85         protected:
86             Aws::String m_logtag;
87 
88         private:
89             std::shared_ptr<Client::RetryStrategy> m_retryStrategy;
90             std::shared_ptr<Http::HttpClient> m_httpClient;
91             Aws::UniquePtr<Client::AWSErrorMarshaller> m_errorMarshaller;
92         };
93 
94         /**
95          * Derived class to support retrieving of EC2 Metadata
96          */
97         class AWS_CORE_API EC2MetadataClient : public AWSHttpResourceClient
98         {
99         public:
100             /**
101              * Build an instance with default EC2 Metadata service endpoint
102              */
103             EC2MetadataClient(const char* endpoint = "http://169.254.169.254");
104             EC2MetadataClient(const Client::ClientConfiguration& clientConfiguration, const char* endpoint = "http://169.254.169.254");
105 
106             EC2MetadataClient& operator =(const EC2MetadataClient& rhs) = delete;
107             EC2MetadataClient(const EC2MetadataClient& rhs) = delete;
108             EC2MetadataClient& operator =(const EC2MetadataClient&& rhs) = delete;
109             EC2MetadataClient(const EC2MetadataClient&& rhs) = delete;
110 
111             virtual ~EC2MetadataClient();
112 
113             using AWSHttpResourceClient::GetResource;
114 
115             /**
116             * Connects to the metadata service to read the specified resource and
117             * returns the text contents. The resource URI = m_endpoint + resourcePath.
118             */
119             virtual Aws::String GetResource(const char* resourcePath) const;
120 
121             /**
122              * Connects to the Amazon EC2 Instance Metadata Service to retrieve the
123              * default credential information (if any).
124              */
125             virtual Aws::String GetDefaultCredentials() const;
126 
127             /**
128              * Connects to the Amazon EC2 Instance Metadata Service to retrieve the
129              * credential information (if any) in a more secure way.
130              */
131             virtual Aws::String GetDefaultCredentialsSecurely() const;
132 
133             /**
134              * connects to the Amazon EC2 Instance metadata Service to retrieve the region
135              * the current EC2 instance is running in.
136              */
137             virtual Aws::String GetCurrentRegion() const;
138 
139             /**
140              * Sets endpoint used to connect to the EC2 Instance metadata Service
141              */
142             virtual void SetEndpoint(const Aws::String& endpoint);
143 
144             /**
145              * Gets endpoint used to connect to the EC2 Instance metadata Service
146              */
147             virtual Aws::String GetEndpoint() const;
148 
149         private:
150             Aws::String m_endpoint;
151             mutable std::recursive_mutex m_tokenMutex;
152             mutable Aws::String m_token;
153             mutable bool m_tokenRequired;
154             mutable Aws::String m_region;
155         };
156 
157         void AWS_CORE_API InitEC2MetadataClient();
158         void AWS_CORE_API CleanupEC2MetadataClient();
159         std::shared_ptr<EC2MetadataClient> AWS_CORE_API GetEC2MetadataClient();
160 
161         /**
162          * Derived class to support retrieving of ECS Credentials
163          */
164         class AWS_CORE_API ECSCredentialsClient : public AWSHttpResourceClient
165         {
166         public:
167             /**
168              * Build an instance with default ECS service endpoint
169              * @param resourcePath The path part of the metadata URL
170              * @param endpoint The URL authority to hit. Default is the IP address of the Task metadata service endpoint.
171              */
172             ECSCredentialsClient(const char* resourcePath, const char* endpoint = "http://169.254.170.2",
173                     const char* authToken = "");
174             ECSCredentialsClient(const Client::ClientConfiguration& clientConfiguration,
175                                  const char* resourcePath, const char* endpoint = "http://169.254.170.2",
176                                  const char* authToken = "");
177 
178             ECSCredentialsClient& operator =(ECSCredentialsClient& rhs) = delete;
179             ECSCredentialsClient(const ECSCredentialsClient& rhs) = delete;
180             ECSCredentialsClient& operator =(ECSCredentialsClient&& rhs) = delete;
181             ECSCredentialsClient(const ECSCredentialsClient&& rhs) = delete;
182 
183             /**
184              * Connects to the Amazon ECS service to retrieve the credential
185              */
GetECSCredentials()186             virtual Aws::String GetECSCredentials() const
187             {
188                 return GetResource(m_endpoint.c_str(), m_resourcePath.c_str(), m_token.c_str());
189             }
190 
191         private:
192             Aws::String m_resourcePath;
193             Aws::String m_endpoint;
194             Aws::String m_token;
195         };
196 
197         /**
198          * To support retrieving credentials from STS.
199          * Note that STS accepts request with protocol of queryxml. Calling GetResource() will trigger
200          * a query request using AWSHttpResourceClient under the hood.
201          */
202         class AWS_CORE_API STSCredentialsClient : public AWSHttpResourceClient
203         {
204         public:
205             /**
206              * Initializes the provider to retrieve credentials from STS when it expires.
207              */
208             STSCredentialsClient(const Client::ClientConfiguration& clientConfiguration);
209 
210             STSCredentialsClient& operator =(STSCredentialsClient& rhs) = delete;
211             STSCredentialsClient(const STSCredentialsClient& rhs) = delete;
212             STSCredentialsClient& operator =(STSCredentialsClient&& rhs) = delete;
213             STSCredentialsClient(const STSCredentialsClient&& rhs) = delete;
214 
215             // If you want to make an AssumeRoleWithWebIdentity call to sts. use these classes to pass data to and get info from STSCredentialsClient client.
216             // If you want to make an AssumeRole call to sts, define the request/result members class/struct like this.
217             struct STSAssumeRoleWithWebIdentityRequest
218             {
219                 Aws::String roleSessionName;
220                 Aws::String roleArn;
221                 Aws::String webIdentityToken;
222             };
223 
224             struct STSAssumeRoleWithWebIdentityResult
225             {
226                 Aws::Auth::AWSCredentials creds;
227             };
228 
229             STSAssumeRoleWithWebIdentityResult GetAssumeRoleWithWebIdentityCredentials(const STSAssumeRoleWithWebIdentityRequest& request);
230 
231         private:
232             Aws::String m_endpoint;
233         };
234 
235         /**
236          * To support retrieving credentials from SSO.
237          */
238          class AWS_CORE_API SSOCredentialsClient : public AWSHttpResourceClient
239          {
240          public:
241              SSOCredentialsClient(const Client::ClientConfiguration& clientConfiguration);
242 
243              SSOCredentialsClient& operator =(SSOCredentialsClient& rhs) = delete;
244              SSOCredentialsClient(const SSOCredentialsClient& rhs) = delete;
245              SSOCredentialsClient& operator =(SSOCredentialsClient&& rhs) = delete;
246              SSOCredentialsClient(SSOCredentialsClient&& rhs) = delete;
247 
248              struct SSOGetRoleCredentialsRequest
249              {
250                  Aws::String m_ssoAccountId;
251                  Aws::String m_ssoRoleName;
252                  Aws::String m_accessToken;
253              };
254 
255              struct SSOGetRoleCredentialsResult
256              {
257                  Aws::Auth::AWSCredentials creds;
258              };
259 
260              SSOGetRoleCredentialsResult GetSSOCredentials(const SSOGetRoleCredentialsRequest& request);
261 
262          private:
263              Aws::String m_endpoint;
264          };
265     } // namespace Internal
266 } // namespace Aws
267