From 05e733a49a2e6996b7558391e12ff30535990a76 Mon Sep 17 00:00:00 2001 From: Jan Rochel Date: Thu, 4 Mar 2021 14:17:37 +0100 Subject: [PATCH 1/2] lib/aws.ml: cosmetics --- lib/aws.ml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/aws.ml b/lib/aws.ml index 62df28dea..ed467d70d 100644 --- a/lib/aws.ml +++ b/lib/aws.ml @@ -530,16 +530,16 @@ module Signing = struct let canonical_querystring = params in let payload_hash = Hash.sha256_hex "" in let canonical_headers = - "host:" - ^ host - ^ "\n" - ^ "x-amz-content-sha256:" - ^ payload_hash - ^ "\nx-amz-date:" - ^ amzdate - ^ "\n" + [ "host", host + ; "x-amz-content-sha256", payload_hash + ; "x-amz-date", amzdate + ] + in + let signed_headers = String.concat ";" (List.map fst canonical_headers) in + let canonical_headers_str = + let add_header acc (name, value) = acc ^ name ^ ":" ^ value ^ "\n" in + List.fold_left add_header "" canonical_headers in - let signed_headers = "host;x-amz-content-sha256;x-amz-date" in let canonical_request = Request.string_of_meth meth ^ "\n" @@ -547,7 +547,7 @@ module Signing = struct ^ "\n" ^ canonical_querystring ^ "\n" - ^ canonical_headers + ^ canonical_headers_str ^ "\n" ^ signed_headers ^ "\n" From 86f267083b1bfe4b0c4b07d37671305149bfd74f Mon Sep 17 00:00:00 2001 From: Jan Rochel Date: Thu, 4 Mar 2021 11:13:58 +0100 Subject: [PATCH 2/2] support for authentification using temporary session tokens according to https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html --- async/runtime.ml | 3 +++ async/runtime.mli | 1 + lib/aws.ml | 24 +++++++++++++++--------- lib/aws.mli | 2 ++ lwt/runtime.ml | 3 +++ lwt/runtime.mli | 1 + 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/async/runtime.ml b/async/runtime.ml index ab3e32f7e..9c2ba176c 100644 --- a/async/runtime.ml +++ b/async/runtime.ml @@ -44,6 +44,7 @@ let run_request ~region ~access_key ~secret_key + ?session_token (module M : Aws.Call with type input = input and type output = output @@ -55,6 +56,7 @@ let run_request Aws.Signing.sign_request ~access_key ~secret_key + ?session_token ~service:M.service ~region (M.to_http M.service region inp) @@ -62,6 +64,7 @@ let run_request Aws.Signing.sign_v2_request ~access_key ~secret_key + ?session_token ~service:M.service ~region (M.to_http M.service region inp) diff --git a/async/runtime.mli b/async/runtime.mli index 579d4c9dc..744137945 100644 --- a/async/runtime.mli +++ b/async/runtime.mli @@ -35,6 +35,7 @@ val run_request : region:string -> access_key:string -> secret_key:string + -> ?session_token:string -> ('input, 'output, 'error) Aws.call -> 'input -> [ `Ok of 'output | `Error of 'error Aws.Error.t ] Async.Deferred.t diff --git a/lib/aws.ml b/lib/aws.ml index ed467d70d..00a9e52a7 100644 --- a/lib/aws.ml +++ b/lib/aws.ml @@ -516,7 +516,7 @@ module Signing = struct (* NOTE(dbp 2015-01-13): This is a direct translation of reference implementation at: * http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html *) - let sign_request ~access_key ~secret_key ~service ~region (meth, uri, headers) = + let sign_request ~access_key ~secret_key ?session_token ~service ~region (meth, uri, headers) = let host = Util.of_option_exn (Endpoints.endpoint_of service region) in let params = encode_query (Uri.query uri) in let sign key msg = Hash.sha256 ~key msg in @@ -534,6 +534,10 @@ module Signing = struct ; "x-amz-content-sha256", payload_hash ; "x-amz-date", amzdate ] + @ + match session_token with + | None -> [] + | Some token -> ["x-amz-security-token", token] in let signed_headers = String.concat ";" (List.map fst canonical_headers) in let canonical_headers_str = @@ -586,23 +590,25 @@ module Signing = struct ] in let headers = - ("x-amz-date", amzdate) - :: ("x-amz-content-sha256", payload_hash) - :: ("Authorization", authorization_header) - :: headers + canonical_headers + @ ["Authorization", authorization_header] + @ headers in meth, uri, headers - let sign_v2_request ~access_key ~secret_key ~service ~region (meth, uri, headers) = + let sign_v2_request ~access_key ~secret_key ?session_token ~service ~region (meth, uri, headers) = let host = Util.of_option_exn (Endpoints.endpoint_of service region) in let amzdate = Time.date_time_iso8601 (Time.now_utc ()) in - let query = Uri.add_query_params' uri - [ "Timestamp", amzdate + let query = + let params = [ "Timestamp", amzdate ; "AWSAccessKeyId", access_key ; "SignatureMethod", "HmacSHA256" ; "SignatureVersion", "2" - ] in + ] + @ match session_token with None -> [] | Some t -> ["SecurityToken", t] + in Uri.add_query_params' uri params + in let params = encode_query (Uri.query query) in let canonical_uri = "/" in diff --git a/lib/aws.mli b/lib/aws.mli index 0de14b5b5..8dc4dce53 100644 --- a/lib/aws.mli +++ b/lib/aws.mli @@ -301,6 +301,7 @@ module Signing : sig val sign_request : access_key:string -> secret_key:string + -> ?session_token:string -> service:string -> region:string -> Request.t @@ -322,6 +323,7 @@ module Signing : sig val sign_v2_request : access_key:string -> secret_key:string + -> ?session_token:string -> service:string -> region:string -> Request.t diff --git a/lwt/runtime.ml b/lwt/runtime.ml index 8d572c4e0..aa32cfe41 100644 --- a/lwt/runtime.ml +++ b/lwt/runtime.ml @@ -38,6 +38,7 @@ let run_request ~region ~access_key ~secret_key + ?session_token (module M : Aws.Call with type input = input and type output = output @@ -49,6 +50,7 @@ let run_request Aws.Signing.sign_request ~access_key ~secret_key + ?session_token ~service:M.service ~region (M.to_http M.service region inp) @@ -56,6 +58,7 @@ let run_request Aws.Signing.sign_v2_request ~access_key ~secret_key + ?session_token ~service:M.service ~region (M.to_http M.service region inp) diff --git a/lwt/runtime.mli b/lwt/runtime.mli index e72eb344f..c38d1b6ab 100644 --- a/lwt/runtime.mli +++ b/lwt/runtime.mli @@ -37,6 +37,7 @@ val run_request : region:string -> access_key:string -> secret_key:string + -> ?session_token:string -> ('input, 'output, 'error) Aws.call -> 'input -> [ `Ok of 'output | `Error of 'error Aws.Error.t ] Lwt.t