如何在Swagger中在请求之前计算AWS签名V4

8
对于我们的AWS API端点,我们使用AWS_IAM授权,并希望从Swagger UI中进行调用。 要进行成功的调用,必须有两个标题"Authorization"和"x-amz-date"。我们使用来自aws文档的以下步骤形成“Authorization”。 我们必须在每次调用时更改“x-amz-date”以通过授权。 问题是:如何编写在每次请求发送到aws之前运行的脚本以签署请求? (我们知道如何在加载Swagger页面之前一次指定两个标题,但此过程应在每次调用之前重新运行)。
提前感谢。

我们正在使用API Gateway和Swagger来定义API,并且一直在尝试找出如何同时使用swagger-codegen生成JS SDK(看起来API Gateway控制台有一个包含sigv4代码的特性或自定义模板)并将该sigv4额外的代码嵌入到swagger文档的JS代码中,即在ApiClient.jsapplyAuthToRequest开关语句中。 - Roberto Andrade
我猜测Swagger文档生成工具的工作方式与Swagger Codegen类似,它可以使用额外的(例如:mustache)模板来自定义输出,包括不同的标记、脚本等。 - Roberto Andrade
猜测一个选项是fork swagger-ui(https://github.com/swagger-api/swagger-ui)并在那里包含相同的sigv4魔法? - Roberto Andrade
根据他们的文档,似乎那是正确的方法。不知道如果在初始化时传递sigv4authorizations参数会有什么作用。 - Roberto Andrade
2个回答

4

swagger-js 中有内置的支持,可以添加 requestInterceptor 来实现这一点。swagger-ui 项目在幕后使用 swagger-js。

只需像这样创建一个请求拦截器:

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

并在创建时将其应用于您的swagger实例:

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

在这里,您可以在request对象中设置头信息(请注意,这不是标准javascript http请求对象,请查看详细信息)。但是您可以在此处访问所有头文件,因此可以根据需要进行计算和注入。


2
你可以很容易地将AWS SDK中的签名monkeypatch到SwaggerJS(因此也可以在SwaggerUI中使用)。请参见这里
我有一个稍微修改过的SwaggerUI,在这里。给定一些AWS凭据和API ID,它将拉取Swagger定义,在SwaggerUI中显示它,然后您可以使用sigv4调用API。
Authorizer实现如下:
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;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接