Skip to content

feat(eventhubs): restore connection string authentication - #7251

Draft
j7nw4r wants to merge 2 commits into
Azure:mainfrom
j7nw4r:worktree-eventhubs-connstring-restore
Draft

feat(eventhubs): restore connection string authentication#7251
j7nw4r wants to merge 2 commits into
Azure:mainfrom
j7nw4r:worktree-eventhubs-connstring-restore

Conversation

@j7nw4r

@j7nw4r j7nw4r commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

This change restores the connection string constructors on ProducerClient and ConsumerClient. Version 1.0.0-beta.11 removed them, which made the C++ library the only Event Hubs SDK without a connection string entry point. The change also restores Event Hubs emulator support, which depended on those constructors.

Fixes #7250.

Motivation

The removal arrived with commit e04e96cf8 ("Merged Rust AMQP stack with main.", #6442), a large merge that rebuilt the AMQP layer. The CHANGELOG.md records the removal as a breaking change, and neither the entry nor the commit message states a rationale.

The Azure SDK guidelines permit the restoration. general-auth-connection-strings states "DO NOT support constructing a service client with a connection string unless such connection string is available within tooling (for copy/paste operations)." Event Hubs publishes connection strings in the Azure portal under the shared access policies of a namespace, so the exception applies.

The supporting code was never deleted. ConnectionStringParser and ServiceBusSasConnectionStringCredential still live in azure-core-amqp, still build for both the uAMQP and the Rust AMQP backends, and still have unit tests. ServiceBusSasConnectionStringCredential derives from Azure::Core::Credentials::TokenCredential, so the restored constructors parse the string, build the credential, and delegate to the existing token credential path. The AMQP connection layer already branches on IsSasCredential() to select the CBS token type, so the transport needs no change.

Two effects of the removal made this worth fixing. Every sibling Event Hubs SDK exposes a connection string entry point: .NET, Go, Java, Python, and Rust. And the Event Hubs emulator does not support Microsoft Entra ID, so a connection string is its only credential. The dead constant EventHubsServiceScheme_Emulator still sat in eventhubs_constants.hpp with no code path able to reach it.

Changes

  • Restored ProducerClient(connectionString, eventHub, options) and ConsumerClient(connectionString, eventHub, consumerGroup, options) with their pre-removal signatures.
  • Restored the emulator path. When the connection string sets UseDevelopmentEmulator=true, the constructor selects the amqp:// scheme and sets the target port to AmqpPort. Both AMQP backends derive the transport from the port, so that one assignment disables TLS.
  • Kept ServiceBusSasConnectionStringCredential inside the .cpp files. The public headers gain no azure/core/amqp/internal/* include, so this change does not add to the internal header leakage in the public surface.
  • Restored the ConnectionString authentication type in the test base, and restored the ConnectionString parameterization in the producer, consumer, processor, and round trip suites. The ConnectionString_LIVEONLY_ suffix gates them to live runs.
  • Added 11 offline constructor tests that need no live Event Hub. They cover EntityPath adoption, a matching event hub name, the mismatch throw, a caller supplied name, namespace extraction, the default consumer group, and the emulator connection string.
  • Restored the four deleted connection string samples. samples/README.md still listed all four.
  • Corrected the package README.md. It documented the removed constructors, and its examples used EventDataBatch direct construction, AddMessage, and SendEventDataBatch, none of which exist on the current surface.
  • Corrected the connection string environment variable name in samples/README.md from EVENTHUBS_CONNECTION_STRING to EVENTHUB_CONNECTION_STRING, which is the name that the sample code and ci.yml use.

EntityPath precedence

The behavior matches .NET. An empty eventHub parameter adopts the EntityPath value, a matching value passes, and a different value throws std::invalid_argument. ServiceBusSasConnectionStringCredential already implements this rule, so the clients inherit it by delegation.

One deviation from .NET: the C++ credential compares the two names exactly, and .NET compares them without case. This change keeps the exact compare, because changing the shared credential would also change Service Bus behavior.

Validation

Built and tested on macOS arm64 with the uAMQP backend.

cmake -B build-uamqp -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
  -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DDISABLE_RUST_IN_BUILD=ON
make azure-messaging-eventhubs azure-messaging-eventhubs-test -j8
AZURE_TEST_MODE=PLAYBACK EVENTHUB_CONSUMER_GROUP='$Default' ./azure-messaging-eventhubs-test

Results: the library and the test binary build clean. The full suite reports 97 tests, 39 passed, 0 failed, and 117 live only cases skipped. All 11 new offline tests pass.

Note on CheckpointStoreTest.TestCheckpoints: it fails without the EVENTHUB_CONSUMER_GROUP environment variable, on this branch and on main. That behavior predates this change, and this change does not touch the checkpoint store.

Work not done in this pull request

  • Live connection string tests cannot pass yet. test-resources.json sets "disableLocalAuth": true on the test namespace, and the outputs block exports no connection string. Enabling shared access key authentication on the test subscription needs engineering system sign off, so this change leaves the resource template alone. The restored ConnectionString parameterizations stay dormant until the environment variable exists.
  • The emulator path has no automated coverage. CI provisions no emulator. The analysis is that the port assignment is the whole TLS story on both backends, and the offline test makes sure the emulator connection string constructs. A manual run against the Docker emulator is still the only end to end proof.
  • The Rust AMQP backend build is unverified here. Only the uAMQP backend was built locally. The new code calls no backend specific API, and connection_string_credential.cpp builds for both backends, so CI should cover this.
  • BlobCheckpointStore keeps its current surface. It takes a BlobContainerClient, and Azure Storage already ships BlobContainerClient::CreateFromConnectionString, so a connection string user has a path with no new API.
  • The performance test still misuses EVENTHUB_CONNECTION_STRING. It reads that variable into a host name field and passes it with a token credential (test/perf/inc/azure/messaging/eventhubs/test/eventhubs_batch_perf_test.hpp). That is a separate latent defect from the removal, and it is a natural follow up.

Version 1.0.0-beta.11 removed the connection string constructors from
ProducerClient and ConsumerClient. The removal arrived with the Rust AMQP
stack merge (Azure#6442) and no rationale was recorded.

The supporting code was never deleted. ConnectionStringParser and
ServiceBusSasConnectionStringCredential still live in azure-core-amqp,
still build for both AMQP backends, and still have tests. The credential
derives from TokenCredential, so the restored constructors parse the
string, build the credential, and delegate to the existing token path.

This also restores Event Hubs emulator support. The emulator does not
support Microsoft Entra ID, so a connection string is its only
credential. The dead EventHubsServiceScheme_Emulator constant becomes
reachable again.

The credential already implements the EntityPath precedence rule that
.NET uses: an empty caller name adopts EntityPath, a matching name
passes, and a different name throws std::invalid_argument.

Adds offline constructor tests that need no live Event Hub, restores the
ConnectionString parameterization in the live suites, restores the four
deleted connection string samples, and corrects the README examples,
which documented the removed API and stale batch calls.

Fixes Azure#7250
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
7 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Three CI failures came from the connection string restoration.

The produce_events sample called Value() on EventDataBatchOptions
PartitionId, which is a std::string and not a Nullable. The call did
not compile. Print the member directly.

The cspell task flagged fragments of the fake base64 keys in the new
offline tests. Wrap the connection string constants in cspell disable
and enable markers, as other tests in the repository do.

The link checker rejected the four relative sample links in the
README. Only .github, eng, and evals may use relative links. Use
absolute GitHub URLs, which is the pattern the storage READMEs use.
@j7nw4r

j7nw4r commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

The cpp - core - ci failures on this PR are not from this change. This branch touches no file under sdk/core.

That pipeline broke on main on 2026-07-27 and has failed on every main run since (builds 20260727.2, 20260727.5, 20260727.9). It last passed on 2026-07-24. The failure is in Test-Setup for azure-core-amqp: dotnet build cannot build TestArtifacts/azure-amqp/test/TestAmqpBroker/TestAmqpBroker.csproj for net8.0, so it looks like a missing .NET target framework on the agents rather than a code problem.

Everything this change can affect is green: cpp - eventhubs - ci passes on the full matrix, cpp - storage - ci passes, and Verify Links passes.

I fixed three real failures from the first push. The produce_events sample called .Value() on EventDataBatchOptions::PartitionId, which is a std::string and not a Nullable. cspell flagged fragments of the fake base64 keys in the new offline tests. And the link checker rejected the relative sample links in the README, so those are absolute URLs now.

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.

Restore connection string authentication for the Event Hubs clients

1 participant