Skip to content

Conversation

@christothes
Copy link
Member

Contributing to the Azure SDK

Please see our CONTRIBUTING.md if you are not familiar with contributing to this repository or have questions.

For specific information about pull request etiquette and best practices, see this section.

@christothes christothes requested a review from a team as a code owner November 13, 2025 20:42
Copilot AI review requested due to automatic review settings November 13, 2025 20:42
Copilot finished reviewing on behalf of christothes November 13, 2025 20:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements support for client certificate rotation in the Azure.Core transport layer to enable dynamic token binding scenarios. The changes allow transport instances to be updated with new certificate configurations at runtime without requiring full pipeline reconstruction.

Key Changes:

  • Added UpdateTransport method to HttpPipelineTransport base class and implementations in HttpClientTransport and HttpWebRequestTransport
  • Introduced ISupportsTransportCertificateUpdate interface for policies that need to trigger transport updates
  • Extended AccessToken with a BindingCertificate property for Proof of Possession (PoP) scenarios
  • Added comprehensive test coverage for certificate rotation scenarios (rotating from empty, rotating from existing cert)

Reviewed Changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
sdk/core/Azure.Core/src/Pipeline/Internal/ISupportsTransportUpdate.cs New internal interface for policies that support transport certificate updates via event subscription
sdk/core/Azure.Core/src/Pipeline/HttpPipelineTransport.cs Added virtual UpdateTransport method to base transport class with default NotSupportedException
sdk/core/Azure.Core/src/Pipeline/HttpClientTransport.cs Implemented UpdateTransport with support for client and handler factories, using volatile field and Interlocked for thread-safety
sdk/core/Azure.Core/src/Pipeline/HttpWebRequestTransport.cs Implemented UpdateTransport using Interlocked.Exchange for thread-safe configuration updates
sdk/core/Azure.Core/src/Pipeline/HttpPipeline.cs Added subscription to ISupportsTransportCertificateUpdate events in constructors to enable transport updates
sdk/core/Azure.Core/src/Pipeline/HttpPipelineTransportOptions.cs Added internal Clone method for creating copies of transport options during updates
sdk/core/Azure.Core/src/AccessToken.cs Added BindingCertificate property and constructor overload to support token binding with client certificates
sdk/core/Azure.Core/tests/TransportFunctionalTests.cs Added two new test methods for certificate rotation scenarios plus code formatting improvements
sdk/core/Azure.Core/tests/PipelineTestBase.cs Extracted GetCertificate helper method and added second test certificate constant (Pfx2)
sdk/core/Azure.Core/tests/HttpPipelineTests.cs Added test for transport update mechanism with TransportUpdatingPolicy test class
sdk/core/Azure.Core/tests/HttpClientTransportFunctionalTest.cs Removed unused certCallback field
sdk/core/Azure.Core.TestFramework/src/MockTransport.cs Implemented UpdateTransport to track transport updates in tests
sdk/core/Azure.Core.TestFramework/src/Azure.Core.TestFramework.csproj Changed from PackageReference to ProjectReference for Azure.Core (likely temporary for testing)
sdk/core/Azure.Core/api/*.cs Updated API surface files for all target frameworks with new public constructors and methods

Comment on lines 92 to 100
for (int i = 0; i < pipeline.Length; i++)
{
// If the policy implements ISupportsTransportCertificateUpdate, we need to subscribe to its TransportUpdated event
if (pipeline[i] is ISupportsTransportCertificateUpdate transportUpdated)
{
transportUpdated.TransportOptionsChanged += options => _transport.UpdateTransport(options);
break;
}
}
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicate code from the constructor above (lines 61-69). Consider extracting this logic into a private helper method to avoid code duplication.

Copilot uses AI. Check for mistakes.

protected X509Certificate2 GetCertificate(string pfx)
{
byte[] cer = Convert.FromBase64String(Pfx);
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter pfx is not used in this method. Instead, the method uses the constant Pfx from the class. This should be changed to use the pfx parameter that is passed in.

Suggested change
byte[] cer = Convert.FromBase64String(Pfx);
byte[] cer = Convert.FromBase64String(pfx);

Copilot uses AI. Check for mistakes.

var transport = GetTransport(true, options);

// Initially no client certificate
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "Initially no client certificate" but the code actually sets a client certificate in the options before creating the transport. The comment should say "Initially with first client certificate" or similar to accurately reflect what the code does.

Suggested change
// Initially no client certificate
// Initially with first client certificate (clientCert)

Copilot uses AI. Check for mistakes.
{
if (this == Shared)
{
throw new InvalidOperationException("Cannot update the shared HttpClientTransport instance.");
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message says "Cannot update the shared HttpClientTransport instance" but this is HttpWebRequestTransport, not HttpClientTransport. The error message should be corrected to reference the correct transport type.

Suggested change
throw new InvalidOperationException("Cannot update the shared HttpClientTransport instance.");
throw new InvalidOperationException("Cannot update the shared HttpWebRequestTransport instance.");

Copilot uses AI. Check for mistakes.

private X509Certificate2 GetTestCertificate()
{
// byte[] cer = Convert.FromBase64String(Pfx);
Copy link

Copilot AI Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a commented-out line // byte[] cer = Convert.FromBase64String(Pfx); followed by the same line uncommented. The commented line should be removed as it appears to be leftover from development.

Suggested change
// byte[] cer = Convert.FromBase64String(Pfx);

Copilot uses AI. Check for mistakes.

public bool? ExpectSyncPipeline { get; set; }

public List<HttpPipelineTransportOptions> TransportUpdates { get; } = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this public?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is on the mock transport so that code that is testing this can observe the transport updates that have occurred.

public void Dispose() { }
public override void Process(Azure.Core.HttpMessage message) { }
public override System.Threading.Tasks.ValueTask ProcessAsync(Azure.Core.HttpMessage message) { throw null; }
public override void UpdateTransport(Azure.Core.Pipeline.HttpPipelineTransportOptions options) { }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the method is on transport type, should it be called simply Update?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that makes sense.

@github-actions
Copy link

github-actions bot commented Nov 13, 2025

API Change Check

APIView identified API level changes in this PR and created the following API reviews

Azure.Core

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants