How to send AWS API request in K6

Hi All,

I’m new to K6 and javascript.
I need to get some ‘Amazon CloudWatch’ Metrics in my K6 performance test suite.
Followed the steps given in https://k6.io/docs/examples/http-authentication#aws-signature-v4-authentication, but it doesn’t work.

Is there any other way to send AWS request using AWS Signature in K6

Hi, welcome :slight_smile:

Which k6 version are you using? (Output of k6 version)

AFAIK that’s the only way to authenticate with v4 in k6.

When you say “it doesn’t work”, what exactly doesn’t work? What steps did you take, what errors did you receive, etc.? It’s difficult to help you without being able to reproduce the issue. :slight_smile:

1 Like

There’s an AWS request signing demo that @mstoykov did several months ago: https://gist.github.com/MStoykov/38cc1293daa9080b11e26053589a6865

It’s not very polished, but it shows how this can be done without any browserify or other costly alternatives.

2 Likes

Hi @imiric,

Sorry for the late reply.
The error i was getting when using browserified version of aws4 was -

TypeError: Object has no member 'setPrototypeOf' at file

I’m using k6 version - v0.26.2

I have resolved the issue by referring to solution in - this issue

@ned

is there an example for using APIGW?
I am always encountering 403 Forbidden issue

const signed = aws4.sign(
    {
        region: 'ap-southeast-1',
        service: 'execute-api',
        hostname: 'xxx',
        path: '/API/xxx',
        headers: {
            'x-apigw-api-id': 'xxx',
        },
    },
    {
        accessKeyId: __ENV.AWS_ACCESSKEY,
        secretAccessKey: __ENV.AWS_SECRETKEY,
    },
);
console.log(JSON.stringify(signed))

let res = http.post("https://" + signed.hostname + signed.path + "/xxx", JSON.stringify(bp01_t01_body), {
    headers: signed.headers
})
console.log(JSON.stringify(res))

@xyngfei, sorry, I don’t think we have an example about that. There is a newer version of the library I linked to in my previous post though, in this PR: Add aws by MStoykov · Pull Request #11 · grafana/jslib.k6.io · GitHub

1 Like

Ok, let me look at this first, tvqm.

I wish to share the good news with u. This sample code is working fine with the execute-api service. Hope it can get released as part of the k6 jslib soon.

However, this is some change to handle if no using serviceSubdomain with different target (or host) in the code signWithHeaders function

I did not understand what you meant, but neither serviceSubdomain nor target are required parameters (as far as I remember, I haven’t had time to look at that code in some time)

look at the example below, and this is a kind of a dirty hack, still need a better way to handle it.


let obj = signWithHeaders("POST", "execute-api", "ap-southeast-1", "test.k6.io", "flip_coin.php", body, "", { 'x-api-id': x_api_id }, null)

look at the signWithHeaders keyword
function signWithHeaders(method, service, region = "", target = "", path = "", body = null, query = "", headers = {}, serviceSubdomain = null) {
    var options = { headers: headers, region: region }

    options = fillOptions(options);
    options.headers["X-Amz-Date"] = toTime(options.timestamp)
    // assume no pass any arg, service == execute-api
    if (serviceSubdomain === null) {
        serviceSubdomain = service
    }
    // techdebt - issue with using concat the servicesubdomain
    // console.log("serviceSubdomain: " + serviceSubdomain) 
    // var host = serviceSubDomain.concat(".", options.region, ".amazonaws.com")
    var host = target
    // onsole.log("host: " + host)
    options.headers["Host"] = host

hope I can clear your doubts.

Do you mean that you want to make the request against not the domain that AWS is usually at? I haven’t considered this option and likely we will need even more arguments to the function to support that - please write it in the PR and I am welcoming contributions :slight_smile:

yes, you are right. I will try it out first. thx for your follow up.