grafana/postman-to-k6

AWSv4 post request should include the body when signing

YOU54F opened this issue · 4 comments

Hi,

When we send AWSv4 POST requests using scripts which have been converted from a postman collections using this tool, we should include the stringified body in the signing request as part of the auth method

    body: config.data

in const options

      const options = {
        method: "POST",
        protocol: address.protocol(),
        hostname: address.hostname(),
        port: address.port(),
        path: address.path() + address.search(),
        region: `${pm[Var]("awsRegion")}`,
        service: `${pm[Var]("awsServiceName")}`,
        body: config.data
      };

So this generated portion of the script

    auth(config, Var) {
      const address = new URI(config.address);
      const options = {
        method: "POST",
        protocol: address.protocol(),
        hostname: address.hostname(),
        port: address.port(),
        path: address.path() + address.search(),
        region: `${pm[Var]("awsRegion")}`,
        service: `${pm[Var]("awsServiceName")}`
      };
      const credential = {
        accessKeyId: `${pm[Var]("AccessKeyId")}`,
        secretAccessKey: `${pm[Var]("SecretAccessKey")}`,
        sessionToken: `${pm[Var]("SessionToken")}`
      };
      const signed = aws4.sign(options, credential);
      const [path, query = ""] = signed.path.split("?");
      config.address = new URI()
        .protocol(address.protocol())
        .hostname(signed.hostname)
        .path(path)
        .query(query)
        .toString();
      Object.assign(config.headers, signed.headers);
    }

Would become

    auth(config, Var) {
      const address = new URI(config.address);
      const options = {
        method: "POST",
        protocol: address.protocol(),
        hostname: address.hostname(),
        port: address.port(),
        path: address.path() + address.search(),
        region: `${pm[Var]("awsRegion")}`,
        service: `${pm[Var]("awsServiceName")}`,
        body: config.data
      };
      const credential = {
        accessKeyId: `${pm[Var]("AccessKeyId")}`,
        secretAccessKey: `${pm[Var]("SecretAccessKey")}`,
        sessionToken: `${pm[Var]("SessionToken")}`
      };
      const signed = aws4.sign(options, credential);
      const [path, query = ""] = signed.path.split("?");
      config.address = new URI()
        .protocol(address.protocol())
        .hostname(signed.hostname)
        .path(path)
        .query(query)
        .toString();
      Object.assign(config.headers, signed.headers);
    }

Otherwise we will see the error come back from the API gateway

The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\\n\\nThe Canonical String for this request should have been <redacted>

PS. Thank you for the tool!!!

Hi, and thank you for the report! 🙏🏼

Would you mind checking out branch fix/49 and see whether the introduced change solves the issue you're experiencing?

@simskij change is spot on my mate, feel free to merge!

Please let me know when this is published to npm @simskij thanks again

Sure! I think it will be in about a week or so 👍