<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Calling AWS API using Signature 4 in Application Development and Automation Discussions</title>
    <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165502#M1978472</link>
    <description>&lt;P&gt;Hi Guido&lt;/P&gt;&lt;P&gt;I did get it working.  Here is a simple program that reads an S3 bucket.  You can probably tighten up the code but I wanted to keep it simple so I could get it working.&lt;/P&gt;&lt;P&gt;It didn't cut and paste well from NotePad++.  Not sure why.&lt;/P&gt;&lt;P&gt;You have to replace "FILL IN" with your own AWS secret key and AWS access key.&lt;/P&gt;&lt;P&gt;*&amp;amp;---------------------------------------------------------------------*
*&amp;amp; Report  ZAWS_GET_S3                                                 *
*&amp;amp;                                                                     *
*&amp;amp; Reads an S3 Queue.  Based on this example                           *
*&amp;amp; &lt;A href="https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html" target="test_blank"&gt;https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html&lt;/A&gt;
*&amp;amp;
*&amp;amp; AWS link for sqs API calls
*&amp;amp; &lt;A href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Welcome.html" target="test_blank"&gt;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Welcome.html&lt;/A&gt;
*&amp;amp;
*&amp;amp;  SSH 2020-09-01 - Works                                             *
*&amp;amp;---------------------------------------------------------------------*
*&amp;amp; Note, Polling Factor in AWS assigned to the queue determines how    *
*&amp;amp; often a message is availabel for downloading.  Once it is downloaded *
*&amp;amp;, it moves to the "InFlight" queue.  After x number of seconds, it    *
*&amp;amp; moves back to the being available.                                   *
*&amp;amp;----------------------------------------------------------------------*
REPORT ZAWS_GET_S3.
DATA: utctime   type timestamp,
      utcstring type string,
      amzdate   type string,
      datestamp type string.
DATA: lf                TYPE string.
DATA: AccessKey  TYPE STRING,
      secret_key TYPE STRING.
DATA: method                   type string,
      service                  type string,
      host                     type string,
      region                   type string,
      endpoint                 type string,
      request_parameters       type string,
      canonicalresourcepath    type string,
      canonicalqueryparameters type string,
      canonicalheaders         type string,
      canonicalheadernames     type string,
      canonical_request        type string,
      canonical_request_hash   type string,
      xcanonical_request_hash  type xstring,
      algorithm                type string,
      credential_scope         type string,
      string_to_sign           type string,
      string_to_sign_hash      type string,
      payload                  type string,
      bodyhash                 type string,
      xpayload_hash            type xstring,
      signing_key              type string,
      signature                type string,
      Authorization_Header     type string,
      request_url              type string,
      request_uri              type string.
DATA: AWSkey           TYPE string,
      utf8temp         TYPE xstring,
      kSecret          TYPE xstring,
      kDate            TYPE xstring,
      kRegion          TYPE xstring,
      kService         TYPE xstring,
      kSigningKey      TYPE xstring,
      EF_HMACSTRING    TYPE STRING,
      EF_HMACXSTRING   TYPE XSTRING,
      EF_HMACB64STRING TYPE STRING,
      sSignature       TYPE STRING,
      kSignature       TYPE XSTRING,
      sSigningKey      TYPE STRING,
      StringToSign     TYPE string,
      signedSignature  TYPE string.
DATA: client  TYPE REF TO if_http_client,
      hfields TYPE TIHTTPNVP,
      ffields TYPE TIHTTPNVP.
DATA: code      TYPE I,
      cresponse TYPE string,
      reason    TYPE string.
DATA: ef_hashstring    TYPE STRING,
      EF_HASHXSTRING   TYPE XSTRING,
      EF_HASHB64STRING TYPE STRING,
      EF_HASHX         TYPE XSTRING.
** SELECTION SCREEN ****************************************************
PARAMETERS: PDATE   TYPE CHAR16.
** INITIALIZATION ******************************************************
INITIALIZATION.
  PERFORM UTC_DATETIME_ISO_8601.
  PDATE = AMZDATE(16).
************************************************************************
*  START OF SELECTION                                                  *
************************************************************************
START-OF-SELECTION.
  lf = cl_abap_char_utilities=&amp;gt;newline.       " '\n'.
  payload = ''.
  Secret_Key = 'FILL IN'.
  AccessKey = 'FILL IN'.
  amzdate   = pdate.
  datestamp = amzdate(8).
  service = 's3'.
  method = 'GET'.
  request_parameters = ''.
  canonicalqueryparameters = request_parameters.
  host = 's3.amazonaws.com'.
  region = 'us-east-1'.
  canonicalresourcepath = '/'.
* Need HMAC-SHA256
* Create the signature with the key and the request string
* Values for "if_algorithm
*   SHA256
*   SHA384
*   SHA512
  TRY.
      cl_abap_message_digest=&amp;gt;CALCULATE_HASH_FOR_CHAR(
           EXPORTING
             if_algorithm     = 'SHA256'
             if_data          = payload
*             if_length       =
           IMPORTING
             ef_hashstring    = bodyhash            " Hash value as hex encoded string
             EF_HASHXSTRING   = ef_hashxstring      " Binary hash value as XString
             EF_HASHB64STRING = ef_hashb64string    " Hash value as base64 encoded string
             EF_HASHX         = EF_HASHX            " Hash value as XSequence
            ).
    CATCH cx_abap_message_digest. "
      CLEAR bodyhash.
  ENDTRY.
* Must be lower case
  translate bodyhash to lower case.
  canonicalheadernames = 'host;x-amz-content-sha256;x-amz-date'.
  canonicalheaders = 'host:' &amp;amp;&amp;amp; host &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; 'x-amz-content-sha256:' &amp;amp;&amp;amp; bodyhash &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; 'x-amz-date:' &amp;amp;&amp;amp; amzdate &amp;amp;&amp;amp; lf.
*  cl_demo_output=&amp;gt;write_data( bodyhash ).
*  cl_demo_output=&amp;gt;display( ).
* canonical_request
  concatenate method lf canonicalresourcepath lf canonicalqueryparameters lf canonicalheaders lf canonicalheadernames lf bodyhash into canonical_request.
*  cl_demo_output=&amp;gt;write_data( canonical_request ).
*  cl_demo_output=&amp;gt;display( ).
  canonical_request_hash = ''.
  TRY.
      cl_abap_message_digest=&amp;gt;CALCULATE_HASH_FOR_CHAR(
           EXPORTING
             if_algorithm     = 'SHA-256'                " Algorithm Options SHA256 sha-256
             if_data          = canonical_request
*             if_length       =
           IMPORTING
             ef_hashstring    = canonical_request_hash  " Hash value as hex encoded string
             EF_HASHXSTRING   = ef_hashxstring          " Binary hash value as XString
             EF_HASHB64STRING = ef_hashb64string        " Hash value as base64 encoded string
             EF_HASHX         = EF_HASHX                " Hash value as XSequence
            ).
    CATCH cx_abap_message_digest.
      CLEAR canonical_request_hash.
  ENDTRY.
  translate canonical_request_hash to lower case.
*  cl_demo_output=&amp;gt;write_data( canonical_request_hash ).
*  cl_demo_output=&amp;gt;display( ).
  algorithm = 'AWS4-HMAC-SHA256'.
  concatenate datestamp '/' region '/' service '/' 'aws4_request' into credential_scope.
  concatenate algorithm lf amzdate lf credential_scope lf canonical_request_hash into string_to_sign.
*  cl_demo_output=&amp;gt;write_data( string_to_sign ).
*  cl_demo_output=&amp;gt;display( ).
  concatenate 'AWS4' secret_key into AWSkey.
  TRY.
      kSecret = cl_abap_hmac=&amp;gt;string_to_xstring( AWSkey ).
    CATCH cx_abap_message_digest .
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kSecret
             if_data      = datestamp
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kDate
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kDate.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kDate
             if_data      = region
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kRegion
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kRegion.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kRegion
             if_data      = service
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kService
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kService
             if_data      = 'aws4_request'
           IMPORTING
             EF_HMACSTRING    = sSigningKey
             EF_HMACXSTRING   = kSigningKey
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
*  translate sSigningKey to lower case.
*  cl_demo_output=&amp;gt;write_data( sSigningKey ).
*  cl_demo_output=&amp;gt;display( ).
  StringToSign = 'AWS4-HMAC-SHA256' &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; amzdate &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; datestamp &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; region &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; service &amp;amp;&amp;amp; '/aws4_request' &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; canonical_request_hash.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kSigningKey
             if_data      = StringToSign
           IMPORTING
             EF_HMACSTRING    = sSignature
             EF_HMACXSTRING   = kSignature
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
  TRANSLATE sSignature TO LOWER CASE.
*  cl_demo_output=&amp;gt;write_data( StringToSign ).
*  cl_demo_output=&amp;gt;write_data( sSignature ).
*  cl_demo_output=&amp;gt;write_data( kSignature ).
*  cl_demo_output=&amp;gt;write_data( EF_HMACB64STRING ).
*  cl_demo_output=&amp;gt;display( ).
  Authorization_Header = 'AWS4-HMAC-SHA256 Credential=' &amp;amp;&amp;amp; accesskey &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; credential_scope &amp;amp;&amp;amp; ', SignedHeaders=' &amp;amp;&amp;amp; canonicalheadernames &amp;amp;&amp;amp; ', Signature=' &amp;amp;&amp;amp; sSignature.
  request_url = 'https://s3.amazonaws.com/'.
  request_uri = 'https://s3.amazonaws.com/'.
  CALL METHOD cl_http_client=&amp;gt;create_by_url
    EXPORTING
      url                = request_url
      proxy_service      = ''
    IMPORTING
      client             = client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
  IF sy-subrc &amp;lt;&amp;gt; 0.
    write: / 'ERROR creating client.'.
    EXIT.
  ENDIF.
  cl_http_utility=&amp;gt;set_request_uri(
                   request = client-&amp;gt;request
                   uri     = request_uri ).
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'x-amz-content-sha256'
      value = bodyhash.
  client-&amp;gt;propertytype_accept_cookie = client-&amp;gt;co_enabled.
  client-&amp;gt;request-&amp;gt;set_method( if_http_request=&amp;gt;co_request_method_get ).
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'x-amz-date'
      value = amzdate.
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'Host'
      value = host.
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'Authorization'
      value = Authorization_Header.
*  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
*    EXPORTING
*      name  = 'Action'
*      value = 'ListUsers'.
*
*  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
*    EXPORTING
*      name  = 'Version'
*      value = '2010-05-08 HTTP/1.1'.
  CALL METHOD client-&amp;gt;send
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      http_invalid_timeout       = 4
      OTHERS                     = 5.
  CALL METHOD client-&amp;gt;receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      OTHERS                     = 4.
* Get fields returned
  CALL METHOD client-&amp;gt;response-&amp;gt;get_header_fields
    CHANGING
      fields = hfields.
  CALL METHOD client-&amp;gt;response-&amp;gt;get_form_fields
    CHANGING
      fields = ffields.
  CALL METHOD client-&amp;gt;response-&amp;gt;get_status
    IMPORTING
      code   = code
      reason = reason.
  CALL METHOD client-&amp;gt;response-&amp;gt;if_http_entity~get_cdata
    RECEIVING
      data = cresponse.
* This works
* cl_demo_output is failing for some reason
*  cl_demo_output=&amp;gt;display_json( cresponse ).
*  cl_demo_output=&amp;gt;DISPLAY_XML( cresponse ).
  data: l_xml type ref to cl_xml_document .
  create object l_xml.
  call method l_xml-&amp;gt;parse_string
    exporting
      stream = cresponse.              "cresponse is the variable which is holding the xml string
  call method l_xml-&amp;gt;display.
***************************************************************************************
*                                                                                     *
* FORM UTC_DATETIME_ISO_8601                                                          *
*                                                                                     *
***************************************************************************************
FORM UTC_DATETIME_ISO_8601.
  DATA:   lf_date           TYPE    dats,
          lf_time           TYPE    tims,
          lf_timestamp      TYPE    timestampl,
          lf_tz_utc         TYPE    timezone    VALUE   'UTC',
          AMZTS             TYPE    STRING,
          timechar(32)      TYPE    c,
          tempCreatedAfter  TYPE    STRING,
          tempCreatedBefore TYPE    STRING,
          AmazonTimestamp   TYPE    STRING.
  "Amazon can expect a timestamp from any timezone, but for simplicity's sake, we convert
  "our own timestamp to Amazon's own timezone (UTC+0)
  get time stamp field lf_timestamp.
  convert time stamp lf_timestamp
  time zone lf_tz_utc into date lf_date time lf_time.
  MOVE lf_timestamp TO timechar.
  CONDENSE timechar.
  AMZDATE = lf_date(4) &amp;amp;&amp;amp; lf_date+4(2) &amp;amp;&amp;amp; lf_date+6(2) &amp;amp;&amp;amp; 'T' &amp;amp;&amp;amp; lf_time(2) &amp;amp;&amp;amp; lf_time+2(2) &amp;amp;&amp;amp; lf_time+4(2) &amp;amp;&amp;amp; 'Z'.
  TRANSLATE amzdate TO UPPER CASE.
ENDFORM.&lt;/P&gt;&lt;P&gt;Stephen&lt;/P&gt;</description>
    <pubDate>Mon, 03 May 2021 13:19:40 GMT</pubDate>
    <dc:creator>Stephen3</dc:creator>
    <dc:date>2021-05-03T13:19:40Z</dc:date>
    <item>
      <title>Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165500#M1978470</link>
      <description>&lt;P&gt;Hi All;&lt;/P&gt;
  &lt;P&gt;I have already asked this question but provide a complicated example program. To simplify the question, I am trying to duplicate the results from this AWS example:&lt;/P&gt;
  &lt;P&gt;&lt;A href="https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html" target="test_blank"&gt;https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html&lt;/A&gt;&lt;/P&gt;
  &lt;P&gt;I can get a program to get the results for "Task 1" and "Task 2" as per AWS's example, but I cannot get the Example Signature result. I have a sample program below which hard codes the values for "Task 3" but I still don't get the Example Signature. I can get the desired results using Python but I would think I could get them from ABAP. I think the issue is the Python Command "HexEncode" represents a function that returns a base16 encoding of the result sin lower case as per AWS's explaintion.&lt;/P&gt;
  &lt;P&gt;Does anyone know how to generate a base16 hex xstring? Here is my test program.&lt;/P&gt;
  &lt;P&gt;REPORT ZTEST_CHAR_TO_HEX.&lt;BR /&gt; &lt;BR /&gt; data: sSigningKey type string.&lt;BR /&gt; data: xSigningKey type xstring.&lt;BR /&gt; data: buffer1 type xstring.&lt;BR /&gt; data: StringToSign type string.&lt;BR /&gt; data: lf type string.&lt;BR /&gt; data: sSignature type string,&lt;BR /&gt; kSignature type xstring,&lt;BR /&gt; EF_HMACB64String type string.&lt;BR /&gt; &lt;BR /&gt; DATA: conv TYPE REF TO cl_abap_conv_out_ce.&lt;BR /&gt; &lt;BR /&gt; lf = cl_abap_char_utilities=&amp;gt;newline. " '\n'.&lt;BR /&gt; &lt;BR /&gt; sSigningKey = 'c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9'.&lt;BR /&gt; * Convert to Xstring&lt;BR /&gt; TRY.&lt;BR /&gt; xSigningKey = cl_abap_hmac=&amp;gt;string_to_xstring( sSigningKey ).&lt;BR /&gt; CATCH cx_abap_message_digest .&lt;BR /&gt; ENDTRY.&lt;BR /&gt; &lt;BR /&gt; concatenate 'AWS4-HMAC-SHA256' lf '20150830T123600Z' '20150830/us-east-1/iam/aws4_request' lf 'f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59' into StringToSign.&lt;BR /&gt; &lt;BR /&gt; TRY.&lt;BR /&gt; cl_abap_hmac=&amp;gt;calculate_hmac_for_char(&lt;BR /&gt; EXPORTING&lt;BR /&gt; if_algorithm = 'SHA256'&lt;BR /&gt; if_key = xSigningKey&lt;BR /&gt; if_data = StringToSign&lt;BR /&gt; IMPORTING&lt;BR /&gt; EF_HMACSTRING = sSignature&lt;BR /&gt; EF_HMACXSTRING = kSignature&lt;BR /&gt; EF_HMACB64STRING = EF_HMACB64STRING&lt;BR /&gt; ).&lt;BR /&gt; CATCH cx_abap_message_digest. "&lt;BR /&gt; CLEAR kSignature.&lt;BR /&gt; ENDTRY.&lt;BR /&gt; &lt;BR /&gt; DATA(xstr) = cl_abap_codepage=&amp;gt;convert_to( source = sSignature&lt;BR /&gt; codepage = 'utf-16le' ).&lt;BR /&gt; &lt;BR /&gt; &lt;BR /&gt; cl_demo_output=&amp;gt;write_data( sSignature ).&lt;BR /&gt; cl_demo_output=&amp;gt;write_data( kSignature ).&lt;BR /&gt; cl_demo_output=&amp;gt;write_data( EF_HMACB64STRING ).&lt;BR /&gt; cl_demo_output=&amp;gt;write_data( xstr ).&lt;BR /&gt; cl_demo_output=&amp;gt;display( ).&lt;BR /&gt; &lt;BR /&gt; conv = cl_abap_conv_out_ce=&amp;gt;create(&lt;BR /&gt; encoding = '4102'&lt;BR /&gt; endian = 'L' ).&lt;BR /&gt; &lt;BR /&gt; conv-&amp;gt;convert( EXPORTING data = sSignature&lt;BR /&gt; IMPORTING buffer = buffer1 ).&lt;BR /&gt; &lt;BR /&gt; write: sSignature.&lt;BR /&gt; write: buffer1.&lt;/P&gt;</description>
      <pubDate>Thu, 20 Feb 2020 20:02:44 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165500#M1978470</guid>
      <dc:creator>Stephen3</dc:creator>
      <dc:date>2020-02-20T20:02:44Z</dc:date>
    </item>
    <item>
      <title>Re: Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165501#M1978471</link>
      <description>&lt;P&gt;Dear Stephen,&lt;/P&gt;&lt;P&gt;Did you solved?&lt;/P&gt;&lt;P&gt;I am facing the same problem to get the right signature for aws.&lt;/P&gt;&lt;P&gt;Thank you.&lt;/P&gt;&lt;P&gt;Regards.&lt;/P&gt;</description>
      <pubDate>Mon, 03 May 2021 13:10:05 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165501#M1978471</guid>
      <dc:creator>Sofidel</dc:creator>
      <dc:date>2021-05-03T13:10:05Z</dc:date>
    </item>
    <item>
      <title>Re: Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165502#M1978472</link>
      <description>&lt;P&gt;Hi Guido&lt;/P&gt;&lt;P&gt;I did get it working.  Here is a simple program that reads an S3 bucket.  You can probably tighten up the code but I wanted to keep it simple so I could get it working.&lt;/P&gt;&lt;P&gt;It didn't cut and paste well from NotePad++.  Not sure why.&lt;/P&gt;&lt;P&gt;You have to replace "FILL IN" with your own AWS secret key and AWS access key.&lt;/P&gt;&lt;P&gt;*&amp;amp;---------------------------------------------------------------------*
*&amp;amp; Report  ZAWS_GET_S3                                                 *
*&amp;amp;                                                                     *
*&amp;amp; Reads an S3 Queue.  Based on this example                           *
*&amp;amp; &lt;A href="https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html" target="test_blank"&gt;https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html&lt;/A&gt;
*&amp;amp;
*&amp;amp; AWS link for sqs API calls
*&amp;amp; &lt;A href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Welcome.html" target="test_blank"&gt;https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/Welcome.html&lt;/A&gt;
*&amp;amp;
*&amp;amp;  SSH 2020-09-01 - Works                                             *
*&amp;amp;---------------------------------------------------------------------*
*&amp;amp; Note, Polling Factor in AWS assigned to the queue determines how    *
*&amp;amp; often a message is availabel for downloading.  Once it is downloaded *
*&amp;amp;, it moves to the "InFlight" queue.  After x number of seconds, it    *
*&amp;amp; moves back to the being available.                                   *
*&amp;amp;----------------------------------------------------------------------*
REPORT ZAWS_GET_S3.
DATA: utctime   type timestamp,
      utcstring type string,
      amzdate   type string,
      datestamp type string.
DATA: lf                TYPE string.
DATA: AccessKey  TYPE STRING,
      secret_key TYPE STRING.
DATA: method                   type string,
      service                  type string,
      host                     type string,
      region                   type string,
      endpoint                 type string,
      request_parameters       type string,
      canonicalresourcepath    type string,
      canonicalqueryparameters type string,
      canonicalheaders         type string,
      canonicalheadernames     type string,
      canonical_request        type string,
      canonical_request_hash   type string,
      xcanonical_request_hash  type xstring,
      algorithm                type string,
      credential_scope         type string,
      string_to_sign           type string,
      string_to_sign_hash      type string,
      payload                  type string,
      bodyhash                 type string,
      xpayload_hash            type xstring,
      signing_key              type string,
      signature                type string,
      Authorization_Header     type string,
      request_url              type string,
      request_uri              type string.
DATA: AWSkey           TYPE string,
      utf8temp         TYPE xstring,
      kSecret          TYPE xstring,
      kDate            TYPE xstring,
      kRegion          TYPE xstring,
      kService         TYPE xstring,
      kSigningKey      TYPE xstring,
      EF_HMACSTRING    TYPE STRING,
      EF_HMACXSTRING   TYPE XSTRING,
      EF_HMACB64STRING TYPE STRING,
      sSignature       TYPE STRING,
      kSignature       TYPE XSTRING,
      sSigningKey      TYPE STRING,
      StringToSign     TYPE string,
      signedSignature  TYPE string.
DATA: client  TYPE REF TO if_http_client,
      hfields TYPE TIHTTPNVP,
      ffields TYPE TIHTTPNVP.
DATA: code      TYPE I,
      cresponse TYPE string,
      reason    TYPE string.
DATA: ef_hashstring    TYPE STRING,
      EF_HASHXSTRING   TYPE XSTRING,
      EF_HASHB64STRING TYPE STRING,
      EF_HASHX         TYPE XSTRING.
** SELECTION SCREEN ****************************************************
PARAMETERS: PDATE   TYPE CHAR16.
** INITIALIZATION ******************************************************
INITIALIZATION.
  PERFORM UTC_DATETIME_ISO_8601.
  PDATE = AMZDATE(16).
************************************************************************
*  START OF SELECTION                                                  *
************************************************************************
START-OF-SELECTION.
  lf = cl_abap_char_utilities=&amp;gt;newline.       " '\n'.
  payload = ''.
  Secret_Key = 'FILL IN'.
  AccessKey = 'FILL IN'.
  amzdate   = pdate.
  datestamp = amzdate(8).
  service = 's3'.
  method = 'GET'.
  request_parameters = ''.
  canonicalqueryparameters = request_parameters.
  host = 's3.amazonaws.com'.
  region = 'us-east-1'.
  canonicalresourcepath = '/'.
* Need HMAC-SHA256
* Create the signature with the key and the request string
* Values for "if_algorithm
*   SHA256
*   SHA384
*   SHA512
  TRY.
      cl_abap_message_digest=&amp;gt;CALCULATE_HASH_FOR_CHAR(
           EXPORTING
             if_algorithm     = 'SHA256'
             if_data          = payload
*             if_length       =
           IMPORTING
             ef_hashstring    = bodyhash            " Hash value as hex encoded string
             EF_HASHXSTRING   = ef_hashxstring      " Binary hash value as XString
             EF_HASHB64STRING = ef_hashb64string    " Hash value as base64 encoded string
             EF_HASHX         = EF_HASHX            " Hash value as XSequence
            ).
    CATCH cx_abap_message_digest. "
      CLEAR bodyhash.
  ENDTRY.
* Must be lower case
  translate bodyhash to lower case.
  canonicalheadernames = 'host;x-amz-content-sha256;x-amz-date'.
  canonicalheaders = 'host:' &amp;amp;&amp;amp; host &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; 'x-amz-content-sha256:' &amp;amp;&amp;amp; bodyhash &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; 'x-amz-date:' &amp;amp;&amp;amp; amzdate &amp;amp;&amp;amp; lf.
*  cl_demo_output=&amp;gt;write_data( bodyhash ).
*  cl_demo_output=&amp;gt;display( ).
* canonical_request
  concatenate method lf canonicalresourcepath lf canonicalqueryparameters lf canonicalheaders lf canonicalheadernames lf bodyhash into canonical_request.
*  cl_demo_output=&amp;gt;write_data( canonical_request ).
*  cl_demo_output=&amp;gt;display( ).
  canonical_request_hash = ''.
  TRY.
      cl_abap_message_digest=&amp;gt;CALCULATE_HASH_FOR_CHAR(
           EXPORTING
             if_algorithm     = 'SHA-256'                " Algorithm Options SHA256 sha-256
             if_data          = canonical_request
*             if_length       =
           IMPORTING
             ef_hashstring    = canonical_request_hash  " Hash value as hex encoded string
             EF_HASHXSTRING   = ef_hashxstring          " Binary hash value as XString
             EF_HASHB64STRING = ef_hashb64string        " Hash value as base64 encoded string
             EF_HASHX         = EF_HASHX                " Hash value as XSequence
            ).
    CATCH cx_abap_message_digest.
      CLEAR canonical_request_hash.
  ENDTRY.
  translate canonical_request_hash to lower case.
*  cl_demo_output=&amp;gt;write_data( canonical_request_hash ).
*  cl_demo_output=&amp;gt;display( ).
  algorithm = 'AWS4-HMAC-SHA256'.
  concatenate datestamp '/' region '/' service '/' 'aws4_request' into credential_scope.
  concatenate algorithm lf amzdate lf credential_scope lf canonical_request_hash into string_to_sign.
*  cl_demo_output=&amp;gt;write_data( string_to_sign ).
*  cl_demo_output=&amp;gt;display( ).
  concatenate 'AWS4' secret_key into AWSkey.
  TRY.
      kSecret = cl_abap_hmac=&amp;gt;string_to_xstring( AWSkey ).
    CATCH cx_abap_message_digest .
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kSecret
             if_data      = datestamp
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kDate
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kDate.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kDate
             if_data      = region
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kRegion
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kRegion.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kRegion
             if_data      = service
           IMPORTING
             EF_HMACSTRING    = EF_HMACSTRING
             EF_HMACXSTRING   = kService
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kService
             if_data      = 'aws4_request'
           IMPORTING
             EF_HMACSTRING    = sSigningKey
             EF_HMACXSTRING   = kSigningKey
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
*  translate sSigningKey to lower case.
*  cl_demo_output=&amp;gt;write_data( sSigningKey ).
*  cl_demo_output=&amp;gt;display( ).
  StringToSign = 'AWS4-HMAC-SHA256' &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; amzdate &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; datestamp &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; region &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; service &amp;amp;&amp;amp; '/aws4_request' &amp;amp;&amp;amp; lf &amp;amp;&amp;amp; canonical_request_hash.
  TRY.
      cl_abap_hmac=&amp;gt;calculate_hmac_for_char(
           EXPORTING
             if_algorithm = 'SHA256'
             if_key       = kSigningKey
             if_data      = StringToSign
           IMPORTING
             EF_HMACSTRING    = sSignature
             EF_HMACXSTRING   = kSignature
             EF_HMACB64STRING = EF_HMACB64STRING
            ).
    CATCH cx_abap_message_digest. "
      CLEAR kService.
  ENDTRY.
  TRANSLATE sSignature TO LOWER CASE.
*  cl_demo_output=&amp;gt;write_data( StringToSign ).
*  cl_demo_output=&amp;gt;write_data( sSignature ).
*  cl_demo_output=&amp;gt;write_data( kSignature ).
*  cl_demo_output=&amp;gt;write_data( EF_HMACB64STRING ).
*  cl_demo_output=&amp;gt;display( ).
  Authorization_Header = 'AWS4-HMAC-SHA256 Credential=' &amp;amp;&amp;amp; accesskey &amp;amp;&amp;amp; '/' &amp;amp;&amp;amp; credential_scope &amp;amp;&amp;amp; ', SignedHeaders=' &amp;amp;&amp;amp; canonicalheadernames &amp;amp;&amp;amp; ', Signature=' &amp;amp;&amp;amp; sSignature.
  request_url = 'https://s3.amazonaws.com/'.
  request_uri = 'https://s3.amazonaws.com/'.
  CALL METHOD cl_http_client=&amp;gt;create_by_url
    EXPORTING
      url                = request_url
      proxy_service      = ''
    IMPORTING
      client             = client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
  IF sy-subrc &amp;lt;&amp;gt; 0.
    write: / 'ERROR creating client.'.
    EXIT.
  ENDIF.
  cl_http_utility=&amp;gt;set_request_uri(
                   request = client-&amp;gt;request
                   uri     = request_uri ).
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'x-amz-content-sha256'
      value = bodyhash.
  client-&amp;gt;propertytype_accept_cookie = client-&amp;gt;co_enabled.
  client-&amp;gt;request-&amp;gt;set_method( if_http_request=&amp;gt;co_request_method_get ).
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'x-amz-date'
      value = amzdate.
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'Host'
      value = host.
  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
    EXPORTING
      name  = 'Authorization'
      value = Authorization_Header.
*  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
*    EXPORTING
*      name  = 'Action'
*      value = 'ListUsers'.
*
*  CALL METHOD client-&amp;gt;request-&amp;gt;set_header_field
*    EXPORTING
*      name  = 'Version'
*      value = '2010-05-08 HTTP/1.1'.
  CALL METHOD client-&amp;gt;send
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      http_invalid_timeout       = 4
      OTHERS                     = 5.
  CALL METHOD client-&amp;gt;receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      OTHERS                     = 4.
* Get fields returned
  CALL METHOD client-&amp;gt;response-&amp;gt;get_header_fields
    CHANGING
      fields = hfields.
  CALL METHOD client-&amp;gt;response-&amp;gt;get_form_fields
    CHANGING
      fields = ffields.
  CALL METHOD client-&amp;gt;response-&amp;gt;get_status
    IMPORTING
      code   = code
      reason = reason.
  CALL METHOD client-&amp;gt;response-&amp;gt;if_http_entity~get_cdata
    RECEIVING
      data = cresponse.
* This works
* cl_demo_output is failing for some reason
*  cl_demo_output=&amp;gt;display_json( cresponse ).
*  cl_demo_output=&amp;gt;DISPLAY_XML( cresponse ).
  data: l_xml type ref to cl_xml_document .
  create object l_xml.
  call method l_xml-&amp;gt;parse_string
    exporting
      stream = cresponse.              "cresponse is the variable which is holding the xml string
  call method l_xml-&amp;gt;display.
***************************************************************************************
*                                                                                     *
* FORM UTC_DATETIME_ISO_8601                                                          *
*                                                                                     *
***************************************************************************************
FORM UTC_DATETIME_ISO_8601.
  DATA:   lf_date           TYPE    dats,
          lf_time           TYPE    tims,
          lf_timestamp      TYPE    timestampl,
          lf_tz_utc         TYPE    timezone    VALUE   'UTC',
          AMZTS             TYPE    STRING,
          timechar(32)      TYPE    c,
          tempCreatedAfter  TYPE    STRING,
          tempCreatedBefore TYPE    STRING,
          AmazonTimestamp   TYPE    STRING.
  "Amazon can expect a timestamp from any timezone, but for simplicity's sake, we convert
  "our own timestamp to Amazon's own timezone (UTC+0)
  get time stamp field lf_timestamp.
  convert time stamp lf_timestamp
  time zone lf_tz_utc into date lf_date time lf_time.
  MOVE lf_timestamp TO timechar.
  CONDENSE timechar.
  AMZDATE = lf_date(4) &amp;amp;&amp;amp; lf_date+4(2) &amp;amp;&amp;amp; lf_date+6(2) &amp;amp;&amp;amp; 'T' &amp;amp;&amp;amp; lf_time(2) &amp;amp;&amp;amp; lf_time+2(2) &amp;amp;&amp;amp; lf_time+4(2) &amp;amp;&amp;amp; 'Z'.
  TRANSLATE amzdate TO UPPER CASE.
ENDFORM.&lt;/P&gt;&lt;P&gt;Stephen&lt;/P&gt;</description>
      <pubDate>Mon, 03 May 2021 13:19:40 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165502#M1978472</guid>
      <dc:creator>Stephen3</dc:creator>
      <dc:date>2021-05-03T13:19:40Z</dc:date>
    </item>
    <item>
      <title>Re: Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165503#M1978473</link>
      <description>&lt;P&gt;Hi Stephen,&lt;/P&gt;&lt;P&gt;I am stuck hard time trying to write flat file to AWS server using ABAP.&lt;/P&gt;&lt;P&gt;Could you please send sample code for PUT method.&lt;/P&gt;&lt;P&gt;Thanks.&lt;/P&gt;</description>
      <pubDate>Fri, 14 Oct 2022 19:41:12 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165503#M1978473</guid>
      <dc:creator>former_member433346</dc:creator>
      <dc:date>2022-10-14T19:41:12Z</dc:date>
    </item>
    <item>
      <title>Re: Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165504#M1978474</link>
      <description>&lt;P&gt;Hi Ahmed&lt;/P&gt;&lt;P&gt;I will look around.  I don't think we every used PUT.  Just GET.  Conceptually it should work once you have successfully logged into AWS.  Have you been able to get the "GET" working?&lt;/P&gt;&lt;P&gt;Stephen&lt;/P&gt;</description>
      <pubDate>Fri, 14 Oct 2022 19:48:25 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165504#M1978474</guid>
      <dc:creator>Stephen3</dc:creator>
      <dc:date>2022-10-14T19:48:25Z</dc:date>
    </item>
    <item>
      <title>Re: Calling AWS API using Signature 4</title>
      <link>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165505#M1978475</link>
      <description>&lt;P&gt;Hi Stephen,&lt;/P&gt;&lt;P&gt;I am able to write the empty file to AWS server, but not the content. &lt;/P&gt;&lt;P&gt;Any pointers would be highly appreciated.&lt;/P&gt;</description>
      <pubDate>Tue, 18 Oct 2022 03:08:47 GMT</pubDate>
      <guid>https://community.sap.com/t5/application-development-and-automation-discussions/calling-aws-api-using-signature-4/m-p/12165505#M1978475</guid>
      <dc:creator>former_member433346</dc:creator>
      <dc:date>2022-10-18T03:08:47Z</dc:date>
    </item>
  </channel>
</rss>

