Search code examples
scalaamazon-web-servicesrestapigatling

How to send gatling request with AWS Signature Version 4?


I am trying to automate a scenario where I need to generate load on Pods which are hosted on AWS. They require authentication with "AWS Signature Version 4".

I am not sure how to send a request with "AWS Signature Version 4" via Gatling. AWS Signature Version 4 takes these values.

  1. AccessKey
  2. SecretKey
  3. AWS Region
  4. Service Name

Returns

"X-Amz-Date":
"Authorization": "AWS4-HMAC-SHA256 Credential=AccessKey/us-east-1/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature="somevalue",

Does giving all the values like this will help?

.exec(http("RESTGetOAuthToken")
          .post("")
          .header("Content-Type", "application/x-www-form-urlencoded")
          .header("Content-Type", "application/json")
          .header("X-Amz-Date", "")
          .header("Authorization", "")
          .header("Cache-Control", "no-cache")
        .body(StringBody("""{
  "orders": [
      ]
    }
  ]

Solution

  • You need to generate X-Amz-Date and Authorization details and pass them along with the header. You can use the below class to extract this two information.

    https://github.com/sandipperf/AWS_API_Request_Gatling/blob/master/RequestSigner.scala to extract AWS signature key by providing ASWAccessKey and AWSSecretKey.

    **Here is how you can extract information from your scala test class after importing RequestSigner class **

    val AwsAccessKey = "XXXXXXXXXXXX"
    val AwsSecretKey = "XXXXXXXXXXXXXXXXXXXXXXXX"
    val signature = RequestSigner.sign(
            uriPath = "/Your/URL/HERE",
    
            method = "POST",
            //body = Some("""{ "hello": "foo" }"""),
            body = Some(requestBuildBody),
           //requestBuildBody = your actual request body you are going to pass along with post request 
    
            headers = Seq(("Host", List("XXXXXXXX.execute-api.us-XXXX-2.amazonaws.com"))),
            queryParameters = Seq.empty,
            credentials = new BasicAWSCredentials(AwsAccessKey, AwsSecretKey),
            region = "us-XXXX-2",
            service = "execute-api")
    
    
          val amzStamp = (signature.toString).substring(18, 34)
          val sign = (signature.toString).substring(35, 223)
          AmazonTimeDetails.append(amzStamp).toString
          SignatureDetails.append(sign).toString
    

    From above code you will get X-Amz-Date and signatureDetails , which you need to use in header

        "Host" -> "XXXXXX.execute-api.us-XXXX-X.amazonaws.com",
        "Content-Type" -> "application/json",
        "X-Amz-Date" -> "${amazonTimeDetails}",
        "Authorization" -> "${signatureDetails}")