open-telemetry / opentelemetry-go-contrib

Collection of extensions for OpenTelemetry-Go.
https://opentelemetry.io/
Apache License 2.0
1.21k stars 565 forks source link

otelaws AppendMiddlewares causes S3 pre-signed URLs to stop working #3368

Open lgcmotta opened 1 year ago

lgcmotta commented 1 year ago

Description

When adding the otelaws.AppendMiddlewares(&cfg.APIOptions), all pre-signed URLs for downloading S3 files start to break with code SignatureDoesNotMatch and the message:

"The request signature we calculated does not match the signature you provided. Check your key and signing method."

image

When removing otelaws.AppendMiddlewares(&cfg.APIOptions) they immediately return to work.

I'm attaching an image from a diff window with the generated URLs. The only difference that is not related to the AWS account nor the link expiration time is the X-Amz-SignedHeaders. The URL generated from code with otelaws middlewares has two values host and traceparent, while the one without otelaws middlewares has only host.

image

Packages installed

Code

I created a simple project to demonstrate this behavior.

👉 Code is available here. 👈

This sample exports traces to Jaeger using OTLP with gRPC and opentelemetry-collector-contrib at version 0.68.0.

This is the code with AWS SDK v2 configuration and otelaws middleware:

// ...
cfg, err := config.LoadDefaultConfig(ctx)

otelaws.AppendMiddlewares(&cfg.APIOptions) // This call will make the pre-signed URL to stop work

if err != nil {
    panic(err)
}

client := s3.NewFromConfig(cfg)

presignClient := s3.NewPresignClient(client)

presignParams := &s3.GetObjectInput{
    Bucket: aws.String(os.Getenv("BUCKET_NAME")),
    Key:    aws.String(filename),
}

presignDuration := func(presignOptions *s3.PresignOptions) {
    presignOptions.Expires = 5 * time.Minute
}

presignResult, err := presignClient.PresignGetObject(ctx, presignParams, presignDuration)

if err != nil {
    panic(err)
}

return presignResult.URL

Steps to reproduce:

  docker compose up -d
  export BUCKET_NAME=<your_bucket>
  go run main.go

http://localhost:8080/swagger/index.html

http://localhost:16686/

stefanmcshane commented 1 year ago

We have noticed this also with presigning EKS tokens with otelaws v0.39.0

kazz187 commented 1 year ago

I also faced the same issue. I implemented noOpTextMapPropagator that does nothing because it is not necessary to include the traceparent header in AWS API requests, and used it in the config as a temporary workaround.

type noOpTextMapPropagator struct{}

func (n noOpTextMapPropagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {}

func (n noOpTextMapPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context {
    return ctx
}

func (n noOpTextMapPropagator) Fields() []string {
    return []string{}
}
cfg, _ := config.LoadDefaultConfig(context.Background())
otelaws.AppendMiddlewares(
    &cfg.APIOptions,
    otelaws.WithTextMapPropagator(noOpTextMapPropagator{}),
)
madjar commented 1 year ago

I'm very happy to find this at the end of a long search :)

@kazz187 Thanks a lot for the workaround. I'd like to add that there is a noop propagator available out of the box (which I've found because it's the default in an unconfigured otel): propagation.NewCompositeTextMapPropagator()

0xdeafcafe commented 3 months ago

We've just run into this issue too. Is there a known fix, or do we have to disable the text propagation still?