Add AWS Signature Header to all rest assured requests

Tags: , , ,



I’m trying to call an get api which is hosted in aws api gateway via rest-assured

I’m able to sign the request and make a call. But to sign the request, I need to pass the full url to AWS to generate the Authorization Header.

For Ex. If I’m going to access an an endpoint https://my-aws-api.com/basepath/v1/request/123

I need to sign the request via AWSSigner which needs the full endpoint to do so.

My current approach

String baseURI="https://my-aws-api.com";

String basePath="basepath/v1";

String requestPath="request/123";

String endpoint=baseURI+"/"+basePath+"/"+requestPath;

Map<String,String> signedHeaders= aws4sign(endpoint,defaultHeaders);

  given()
                .log().ifValidationFails()
                .headers(signedHeaders)
  .when()
                .get(endpoint)
  .then()
                .log().ifValidationFails()
                .statusCode(200);

If I do that , then I cant use RestAssured’s baseURI, basePath and path params

I want to access it like

RestAssured.baseURI="https://my-aws-api.com";
RestAssured.basePath="basepath/v1";

given()
                .log().ifValidationFails()
                .pathParam("reqID", "123")
.when()
                .get("request/{reqID}")
.then()
                .log().ifValidationFails()
                .statusCode(200);

AwsSigner

public static Map<String, String> aws4Sign(String endpoint, Map<String, String> headers) throws URISyntaxException {
        String serviceName = "execute-api";
        AWS4Signer aws4Signer = new AWS4Signer();
        aws4Signer.setRegionName(EU_WEST_1.getName());
        aws4Signer.setServiceName(serviceName);
        DefaultRequest defaultRequest = new DefaultRequest(serviceName);
        URI uri = new URI(endpoint);
        defaultRequest.setEndpoint(new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "", "", ""));
        defaultRequest.setHttpMethod(HttpMethodName.GET);
        defaultRequest.setResourcePath(uri.getRawPath());
        defaultRequest.setHeaders(headers);
        aws4Signer.sign(defaultRequest, DefaultAWSCredentialsProviderChain.getInstance().getCredentials());
        return defaultRequest.getHeaders();
    }

So My question is there any way, I can intercept the RestAssured’s request before it makes the call, so that I can get the fully generated end point and add the aws signed header to the call.

Answer

Thanks to @Ashaman.

The Filter Section is what I’m looking for

You can get the uri and other headers that were passed with requests from RequestSpec and then send it to the function to sign them and remove the old headers and put the new headers. Then forward the request

@BeforeAll
public void init() {
    RestAssured.baseURI = "https://my-aws-api.com";
    RestAssured.filters((requestSpec, responseSpec, ctx) -> {
        Map<String, String> headers = requestSpec.getHeaders()
                .asList()
                .stream()
                .collect(Collectors.toMap(Header::getName, Header::getValue));
        Map<String, String> signedHeaders = aws4sign(requestSpec.getURI(), headers);
        requestSpec.removeHeaders();
        requestSpec.headers(signedHeaders);
        return ctx.next(requestSpec, responseSpec);
    });
}

And for the tests I can use the features of Rest Assured normally

given()
        .log().ifValidationFails()
        .pathParam("reqID", "123")
.when()
        .get("request/{reqID}")
.then()
        .log().ifValidationFails()
        .statusCode(200);


Source: stackoverflow