Qore AwsRestClient Module Reference 1.2
Loading...
Searching...
No Matches
AwsRestClient.qm.dox.h
1// -*- mode: c++; indent-tabs-mode: nil -*-
3
4/* AwsRestClient.qm Copyright (C) 2019 - 2022 Qore Technologies, s.r.o.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23*/
24
25// minimum qore version
26
27// require type definitions everywhere
28
29// enable all warnings
30
31// don't use "$" for vars, members, and methods, assume local variable scope
32
33// do not ignore argument errors
34
35
36}
37
95namespace AwsRestClient {
97
104
105public:
107 const DefaultSendEncoding = "gzip";
108
110 const RequiredOptions = ...;
111
112
114 const QoreDigest = CRYPTO_DIGEST_SHA256;
115
117 const AwsSignatureAlgorithm = "AWS4-HMAC-SHA256";
118
120 const AwsTermination = "aws4_request";
121
122private:
123 // the AWS access key ID
124 string aws_keyid;
125 // the AWS secret access key
126 string aws_secret;
127 // the AWS region
128 string aws_region;
129 // the AWS service
130 string aws_service;
131 // is this request for AWS S3?
132 bool aws_s3 = False;
133 // temporary session token
134 string aws_token;
135 // credential scope suffix
136 string credential_scope_suffix;
137
138public:
139
141
207 constructor(hash<auto> opts, *softbool do_not_connect) ;
208
209
210 hash<auto> sendAndDecodeResponse(*data body, string m, string path, hash<auto> hdr, *reference<hash<auto>> info, *softbool decode_errors);
211
212
213 string getSignature(string http_method, string path, reference<hash<auto>> hdr, *data body, date gmtime,
214 string scope, reference<string> signed_headers) {
215 string req_string = getRequestString(http_method, path, \hdr, body, gmtime, scope, \signed_headers);
216
217 // calculate a signature
218 string gmdate = gmtime.format("YYYYMMDD");
219 // 1: key, date
220 binary signing_key = hmac(QoreDigest, gmdate, "AWS4" + aws_secret);
221 // 2: hash, region
222 signing_key = hmac(QoreDigest, aws_region, signing_key);
223 // 3: hash, service
224 signing_key = hmac(QoreDigest, aws_service, signing_key);
225 // 4: hash, termination
226 signing_key = hmac(QoreDigest, AwsTermination, signing_key);
227
228 string sig = hmac(QoreDigest, req_string, signing_key).toHex();
229
230 return sig;
231 }
232
233 private string getRequestString(string http_method, string path, reference<hash<auto>> hdr, *data body, date gmtime,
234 string scope, reference<string> signed_headers) {
235 // get AWS date value
236 string aws_date = gmtime.format("YYYYMMDDTHHmmSS") + "Z";
237 hdr."X-Amz-Date" = aws_date;
238 string csig = getCanonicalSignature(http_method, path, hdr, body, \signed_headers);
239
240 string msg = AwsSignatureAlgorithm + "\n"
241 + aws_date + "\n"
242 + scope + "\n"
243 + csig;
244
245 return msg;
246 }
247
248 private string getCanonicalSignature(string http_method, string path, hash<auto> hdr, *data body,
249 reference<string> signed_headers) {
250 // create the canonical string
251 // 1: HTTP request method
252 string cstr = http_method + "\n";
253
254 // make canonical URI
255 hash<UriQueryInfo> uri_info = parse_uri_query(path);
256
257 // 2: canonical URI parameter
258 string uri = uri_info.method ?? "/";
259
260 // normalize the path if not an S3 request
261 if (!aws_s3);
262
263
264 // URI-encode the path
265 uri = encode_url(uri, False);
266 // non-AWS-S3 requests must be URI-encoded twice
267 // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
268 if (!aws_s3);
269
270 // add to canonical string
271 cstr += uri + "\n";
272
273 // 3: canonical query string
274 if (uri_info.params);
275
276 cstr += "\n";
277
278 // 4: canonical headers
279 // convert header keys to lowercase
280 hdr = map {$1.key.lwr(): $1.value}, hdr.pairIterator();
281 // add host header
282 hdr += {"host": getHostHeaderValue()};
283
284 // sort headers
285 hdr = map {$1: hdr{$1}}, sort(keys hdr);
286
287 cstr += (
288 foldl $1 + $2, (
289 map
290private:
291 static string trimall(string str) { "cls": Class::forName("AwsRestConnection"),
292 "options": RestConnection::ConnectionScheme.options + {
293 "data": <ConnectionOptionInfo>{
294 "type": "string",
295 "desc": "data serialization options are limited to `json` with this object",
296 "allowed_values": (
297 <AllowedValueInfo>{
298 "value": "json",
299 "desc": "use JSON serialization",
300 },
301 ),
302 "default_value": "json",
303 },
304 "aws_keyid": <ConnectionOptionInfo>{
305 "type": "string",
306 "desc": "AWS key ID",
307 },
308 "aws_secret": <ConnectionOptionInfo>{
309 "type": "string",
310 "desc": "the AWS secret access key value",
311 "sensitive": True,
312 },
313 "aws_region": <ConnectionOptionInfo>{
314 "type": "string",
315 "desc": "the AWS region to use (ex: `us-east-1`)",
316 },
317 "aws_service": <ConnectionOptionInfo>{
318 "type": "string",
319 "desc": "the AWS service to use (ex: `iam`)",
320 },
321 "aws_s3": <ConnectionOptionInfo>{
322 "type": "bool",
323 "desc": "set to `True` to flag this object for use with AWS S3, which requires special "
324 "message encoding",
325 "default_value": False,
326 },
327 "aws_token": <ConnectionOptionInfo>{
328 "type": "string",
329 "desc": "a temporary session token from AWS Security Token Service for this HTTP session",
330 },
331 },
332 "required_options": foldl $1 + "," + $2, AwsRestClient::RequiredOptions,
333 };
334 }
335
337
347 constructor(string name, string description, string url, hash<auto> attributes = {}, hash<auto> options = {})
348 ;
349
350
352 string getType();
353
354
356
362 DataProvider::AbstractDataProvider getDataProvider();
363
364
366
371
372
374
379 AwsRestClient getImpl(bool connect = True, *hash<auto> rtopts);
380
382 hash<ConnectionSchemeInfo> getConnectionSchemeInfoImpl();
383};
384};
constructor(hash< auto > opts, *softbool do_not_connect)
creates the object with the given options
bool hasDataProvider()
returns True, as this connection always returns a data provider with the getDataProvider() method
constructor(string name, string description, string url, hash< auto > attributes={}, hash< auto > options={})
creates the AwsRestConnection object
AwsRestClient getImpl(bool connect=True, *hash< auto > rtopts)
returns a AwsRestClient::AwsRestClient object
DataProvider::AbstractDataProvider getDataProvider()
returns a data provider object for this connection
string getType()
returns "awsrest"
const RequiredOptions
required options
Definition: AwsRestClient.qm.dox.h:110
hash< ConnectionSchemeInfo > getConnectionSchemeInfoImpl()
Returns the ConnectionSchemeInfo hash for this object.
const True
const False
auto sort(auto arg)
the AwsRestClient namespace contains all the objects in the AwsRestClient module
Definition: AwsRestClient.qm.dox.h:95