Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js opentelemetry https插件导致错误的aws请求签名_Node.js_Amazon Web Services_Aws Sdk Js_Open Telemetry - Fatal编程技术网

Node.js opentelemetry https插件导致错误的aws请求签名

Node.js opentelemetry https插件导致错误的aws请求签名,node.js,amazon-web-services,aws-sdk-js,open-telemetry,Node.js,Amazon Web Services,Aws Sdk Js,Open Telemetry,在NodeJS应用程序中同时使用@opentelemetry/plugin https和aws sdk时,opentelemetry插件会将traceparent头添加到每个aws请求中。如果不需要在aws sdk中重试,则此功能可以正常工作。aws sdk重试请求时,可能会发生以下错误: InvalidSignatureException:我们计算的请求签名与您提供的签名不匹配。检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅维修文档。 SignatureDesNotMatch:我

在NodeJS应用程序中同时使用
@opentelemetry/plugin https
aws sdk
时,opentelemetry插件会将
traceparent
头添加到每个aws请求中。如果不需要在
aws sdk
中重试,则此功能可以正常工作。aws sdk重试请求时,可能会发生以下错误:

  • InvalidSignatureException:我们计算的请求签名与您提供的签名不匹配。检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅维修文档。
  • SignatureDesNotMatch:我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。
第一个AWS请求包含以下标题:

  • traceparent:'00-32c9b7adee1da37fad593ee38e9e479b-875169606368a166-01'
  • Authorization:'AWS4-HMAC-SHA256 Credential=,SignedHeaders=主机;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-target,签名='
请注意,
SignedHeaders
不包括
traceparent

重试的请求包含以下标头:

  • traceparent:'00-c573e391a455a207469ffa4fb75b3cab-6F20C35628CFCC0-01'
  • 授权:AWS4-HMAC-SHA256凭证=,签名头=主机;痕迹;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-target,签名=
请注意,
SignedHeaders
不包括
traceparent

在发送重试请求之前,
@opentelemetry/plugin https
设置新的
traceparent
头,这使得AWS请求的签名无效

下面是一段再现问题的代码(在达到导致重试的速率限制之前,您可能需要运行脚本几次):

可能的解决办法:

  • 忽略
    @opentelemetry/plugin https
    中对aws的所有调用。
    • 忽略对aws的调用将导致失去aws请求的所有跨度
  • traceparent
    标题添加到
    aws sdk
    -
    aws.Signers.V4.prototype.unsignableHeaders.push中的
    unsignableHeaders
    • 如果另一个节点模块使用不同版本的
      aws sdk
      ,则更改原型似乎是一种黑客行为,也无法处理这种情况
  • 是否有另一种解决方案允许我保留aws请求的跨度,并保证所有aws请求的签名都是正确的

    更新(2020年12月16日):

    这一问题似乎已被解决

    以下代码引发正确的错误(ThrottlingException):

    可能与这里的问题相同:
    const opentelemetry = require("@opentelemetry/api");
    const { NodeTracerProvider } = require("@opentelemetry/node");
    const { SimpleSpanProcessor } = require("@opentelemetry/tracing");
    const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
    
    const provider = new NodeTracerProvider({
        plugins: {
            https: {
                enabled: true,
                path: "@opentelemetry/plugin-https"
            }
        }
    });
    
    const exporter = new JaegerExporter({ serviceName: "test" });
    
    provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
    
    provider.register();
    
    const AWS = require("aws-sdk");
    
    const main = async () => {
        const cwl = new AWS.CloudWatchLogs({ region: "us-east-1" });
    
        const promises = new Array(100).fill(true).map(() => new Promise((resolve, reject) => {
            cwl.describeLogGroups(function (err, data) {
                if (err) {
                    console.log(err.name);
                    console.log("Got error:", err.message);
                    console.log("ERROR Request Authorization:");
                    console.log(this.request.httpRequest.headers.Authorization);
                    console.log("ERROR Request traceparent:");
                    console.log(this.request.httpRequest.headers.traceparent);
                    console.log("Retry count:", this.retryCount);
    
                    reject(err);
                    return;
                }
    
                resolve(data);
            });
        }));
    
        const result = await Promise.all(promises);
    
        console.log(result.length);
    };
    
    main().catch(console.error);
    
    const opentelemetry = require("@opentelemetry/api");
    const { NodeTracerProvider } = require("@opentelemetry/node");
    const { SimpleSpanProcessor } = require("@opentelemetry/tracing");
    const { JaegerExporter } = require("@opentelemetry/exporter-jaeger");
    const { CloudWatchLogs } = require("@aws-sdk/client-cloudwatch-logs");
    
    const provider = new NodeTracerProvider({
        plugins: {
            https: {
                enabled: true,
                path: "@opentelemetry/plugin-https"
            }
        }
    });
    
    const exporter = new JaegerExporter({ serviceName: "test" });
    
    provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
    
    provider.register();
    
    const main = async () => {
        const cwl = new CloudWatchLogs({ region: "us-east-1" });
    
        const promises = new Array(100).fill(true).map(() => new Promise((resolve, reject) => {
            cwl.describeLogGroups({ limit: 50 })
                .then(resolve)
                .catch((err) => {
                    console.log(err.name);
                    console.log("Got error:", err.message);
    
                    reject(err);
                });
        }));
    
        const result = await Promise.all(promises);
    
        console.log(result.length);
    };
    
    main().catch(console.error);