How to calculate AWS V4 signature in Swagger before request

For our AWS API endpoints, we use AWS_IAM authorization and want to make a call from the Swagger user interface. To make a successful call, the "Authorization" of the headers and the "x-amz-date" must be specified. To form an β€œAuthorization”, we use the following steps from the aws document . We must change the "x-amz-date" with each call in order to be authorized. The question arises: how to write a script in Swagger to sign a request that runs every time before sending an aws request? (We know how to specify both headers once before loading the Swagger page, but this process must be restarted before each call .)

Thanks in advance.

+5
source share
2 answers

Swagger-js has built-in support to add requestInterceptor to do this. The swagger-ui project uses swagger-js under the hood.

Just create a request interceptor like this:

 requestInterceptor: { apply: function (request) { // modify the request object here return request; } } 

and apply it to the swagger instance when creating:

 window.swaggerUi = new SwaggerUi({ url: url, dom_id: "swagger-ui-container", requestInterceptor: requestInterceptor, 

Here you can set the headers in the request object (note that this is not a standard javascript HTTP request object, check it for details). But you have access to all the headers here, so you can count and enter them as needed.

+3
source

You can pretty easily sign monkeypatch from the AWS SDK to SwaggerJS (and therefore SwaggerUI). See here

I have a slightly modified SwaggerUI here . Given some AWS credentials and an API identifier, it will pull out the Swagger definition, display it in the SwaggerUI, and then you can invoke the API using sigv4.

The Authorizer implementation is as follows:

 var AWSSigv4RequestSigner = function(credentialProvider, aws) { this.name = "sigv4"; this.aws = aws; this.credentialProvider = credentialProvider; }; AWSSigv4RequestSigner.prototype.apply = function(options, authorizations) { var serviceName = "execute-api"; //If we are loading the definition itself, then we need to sign for apigateway. if (options && options.url.indexOf("apigateway") >= 0) { serviceName = "apigateway"; } if(serviceName == "apigateway" || (options.operation && options.operation.authorizations && options.operation.authorizations[0].sigv4)) { /** * All of the below is an adapter to get this thing into the right form for the AWS JS SDK Signer */ var parts = options.url.split('?'); var host = parts[0].substr(8, parts[0].indexOf("/", 8) - 8); var path = parts[0].substr(parts[0].indexOf("/", 8)); var querystring = parts[1]; var now = new Date(); if (!options.headers) { options.headers = []; } options.headers.host = host; if(serviceName == "apigateway") { //For the swagger endpoint, apigateway is strict about content-type options.headers.accept = "application/json"; } options.pathname = function () { return path; }; options.methodIndex = options.method; options.search = function () { return querystring ? querystring : ""; }; options.region = this.aws.config.region || 'us-east-1'; //AWS uses CAPS for method names, but swagger does not. options.method = options.methodIndex.toUpperCase(); var signer = new this.aws.Signers.V4(options, serviceName); //Actually add the Authorization header here signer.addAuthorization(this.credentialProvider, now); //SwaggerJS/yourbrowser complains if these are still around delete options.search; delete options.pathname; delete options.headers.host; return true; } return false; }; 
0
source

Source: https://habr.com/ru/post/1246161/


All Articles