From ea269cbc686037fc3409aef128e339e9bcfe7b19 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Wed, 15 Oct 2025 17:17:49 -0700 Subject: [PATCH 1/2] Fix issue with signature mismatch during retries --- .../CrtAWS4aSigner.cs | 4 +++- .../40b3493b-5041-4ba8-b5b9-75442cfd4fe6.json | 18 ++++++++++++++++++ .../Amazon.Runtime/Internal/Auth/AWS4Signer.cs | 4 +++- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 generator/.DevConfigs/40b3493b-5041-4ba8-b5b9-75442cfd4fe6.json diff --git a/extensions/src/AWSSDK.Extensions.CrtIntegration/CrtAWS4aSigner.cs b/extensions/src/AWSSDK.Extensions.CrtIntegration/CrtAWS4aSigner.cs index ad3361423e93..937461f1ca38 100644 --- a/extensions/src/AWSSDK.Extensions.CrtIntegration/CrtAWS4aSigner.cs +++ b/extensions/src/AWSSDK.Extensions.CrtIntegration/CrtAWS4aSigner.cs @@ -346,7 +346,9 @@ public AwsSigningConfig PrepareCRTSigningConfig(AwsSignatureType signatureType, Encoding.ASCII.GetBytes(HeaderKeys.XAmznTraceIdHeader), Encoding.ASCII.GetBytes(HeaderKeys.TransferEncodingHeader), Encoding.ASCII.GetBytes(HeaderKeys.AmzSdkInvocationId), - Encoding.ASCII.GetBytes(HeaderKeys.AmzSdkRequest) + Encoding.ASCII.GetBytes(HeaderKeys.AmzSdkRequest), + Encoding.ASCII.GetBytes(HeaderKeys.UserAgentHeader), + Encoding.ASCII.GetBytes(HeaderKeys.XAmzUserAgentHeader) }; /// diff --git a/generator/.DevConfigs/40b3493b-5041-4ba8-b5b9-75442cfd4fe6.json b/generator/.DevConfigs/40b3493b-5041-4ba8-b5b9-75442cfd4fe6.json new file mode 100644 index 000000000000..cb9f2209ec78 --- /dev/null +++ b/generator/.DevConfigs/40b3493b-5041-4ba8-b5b9-75442cfd4fe6.json @@ -0,0 +1,18 @@ +{ + "core": { + "updateMinimum": true, + "type": "patch", + "changeLogMessages": [ + "Fix issue with signature mismatch during retries" + ] + }, + "extensions": [ + { + "extensionName": "Extensions.CrtIntegration", + "type": "patch", + "changeLogMessages": [ + "Fix issue with signature mismatch during retries" + ] + } + ] +} \ No newline at end of file diff --git a/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs b/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs index 3753da711ea2..1df5c51459d1 100644 --- a/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs +++ b/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs @@ -64,7 +64,9 @@ public class AWS4Signer : AbstractAWSSigner HeaderKeys.XAmznTraceIdHeader, HeaderKeys.TransferEncodingHeader, HeaderKeys.AmzSdkInvocationId, - HeaderKeys.AmzSdkRequest + HeaderKeys.AmzSdkRequest, + HeaderKeys.UserAgentHeader, + HeaderKeys.XAmzUserAgentHeader }; public AWS4Signer() From 384f46b095b6aece84ffbd55952b2175426d2d0d Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Wed, 15 Oct 2025 17:59:34 -0700 Subject: [PATCH 2/2] Add integ tests --- .../S3/IntegrationTests/PutObjectTests.cs | 78 ++++++++++++++++--- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/sdk/test/Services/S3/IntegrationTests/PutObjectTests.cs b/sdk/test/Services/S3/IntegrationTests/PutObjectTests.cs index c483f2abcd53..95147d0358c2 100644 --- a/sdk/test/Services/S3/IntegrationTests/PutObjectTests.cs +++ b/sdk/test/Services/S3/IntegrationTests/PutObjectTests.cs @@ -1,3 +1,12 @@ +using Amazon; +using Amazon.Runtime; +using Amazon.Runtime.Internal.Util; +using Amazon.S3; +using Amazon.S3.Model; +using Amazon.S3.Util; +using Amazon.Util; +using AWSSDK_DotNet.IntegrationTests.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.IO; @@ -6,17 +15,6 @@ using System.Net; using System.Text; using System.Threading; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -using Amazon; -using Amazon.S3; -using Amazon.S3.Model; -using Amazon.S3.Util; -using Amazon.Runtime; -using Amazon.Runtime.Internal.Util; -using AWSSDK_DotNet.IntegrationTests.Utils; -using System.Diagnostics; -using Amazon.Util; using System.Threading.Tasks; namespace AWSSDK_DotNet.IntegrationTests.Tests.S3 @@ -1372,6 +1370,64 @@ public void TestResetStreamPosition() } + [TestMethod] + [TestCategory("S3")] + public async Task ConfirmRetrySignature() + { + var config = new AmazonS3Config + { + RegionEndpoint = Client.Config.RegionEndpoint, + ResignRetries = true + }; + var s3Client = new AmazonS3Client(config); + // This test is response to this PR https://github.com/aws/aws-sdk-net/pull/4050 + // where retries started failing with signature mismatch due to user agent modifications. + // In this test we are confirming all retries are attempted and not failing with signature mismatch. + var stream = new FailOnceStream(new MemoryStream(Encoding.UTF8.GetBytes("ConfirmRetrySignature"))); + PutObjectRequest request = new PutObjectRequest() + { + BucketName = bucketName, + Key = "thestream", + InputStream = stream, + AutoCloseStream = false, + DisablePayloadSigning = true + }; + + ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)request).UserAgentDetails.AddUserAgentComponent("Modifications"); + + await Client.PutObjectAsync(request); + } + + private class FailOnceStream : WrapperStream + { + public FailOnceStream(MemoryStream memoryStream) + : base(memoryStream) + { + } + + bool _firstRead = true; + + + public override int Read(byte[] buffer, int offset, int count) + { + if (_firstRead) + { + _firstRead = false; + throw new IOException("Fake Exception"); + } + return base.Read(buffer, offset, count); + } + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (_firstRead) + { + _firstRead = false; + throw new IOException("Fake Exception"); + } + return base.ReadAsync(buffer, offset, count, cancellationToken); + } + } + private class ErrorStream : WrapperStream { private ErrorStream(Stream stream)