How to calculate AWS signature V4 in Swagger before request

后端 未结 2 920
生来不讨喜
生来不讨喜 2020-12-31 19:41

For our AWS API Endpoints we use AWS_IAM authorization and want to make a call from Swagger UI. To make a successful call there must be 2 headers \'Authorization\' and \'x-

相关标签:
2条回答
  • 2020-12-31 20:05

    You can pretty easily monkeypatch signing from the AWS SDK into SwaggerJS(and thus SwaggerUI). See here

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

    The Authorizer implementation looks like this:

    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 讨论(0)
  • 2020-12-31 20:12

    There is built-in support in swagger-js to add requestInterceptors to do just this. The swagger-ui project uses swagger-js under the hood.

    Simply create a request interceptor like such:

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

    and apply it to your swagger instance on creation:

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

    Here you can set headers in the request object (note, this is not the standard javascript http request object, inspect it for details). But you do have access to all headers here, so you can calculate and inject them as needed.

    0 讨论(0)
提交回复
热议问题