feat(eventhubs): restore connection string authentication - #7251
Conversation
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: 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.
|
The That pipeline broke on Everything this change can affect is green: I fixed three real failures from the first push. The |
Summary
This change restores the connection string constructors on
ProducerClientandConsumerClient. Version1.0.0-beta.11removed 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. TheCHANGELOG.mdrecords 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-stringsstates "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.
ConnectionStringParserandServiceBusSasConnectionStringCredentialstill live inazure-core-amqp, still build for both the uAMQP and the Rust AMQP backends, and still have unit tests.ServiceBusSasConnectionStringCredentialderives fromAzure::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 onIsSasCredential()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_Emulatorstill sat ineventhubs_constants.hppwith no code path able to reach it.Changes
ProducerClient(connectionString, eventHub, options)andConsumerClient(connectionString, eventHub, consumerGroup, options)with their pre-removal signatures.UseDevelopmentEmulator=true, the constructor selects theamqp://scheme and sets the target port toAmqpPort. Both AMQP backends derive the transport from the port, so that one assignment disables TLS.ServiceBusSasConnectionStringCredentialinside the.cppfiles. The public headers gain noazure/core/amqp/internal/*include, so this change does not add to the internal header leakage in the public surface.ConnectionStringauthentication type in the test base, and restored theConnectionStringparameterization in the producer, consumer, processor, and round trip suites. TheConnectionString_LIVEONLY_suffix gates them to live runs.EntityPathadoption, a matching event hub name, the mismatch throw, a caller supplied name, namespace extraction, the default consumer group, and the emulator connection string.samples/README.mdstill listed all four.README.md. It documented the removed constructors, and its examples usedEventDataBatchdirect construction,AddMessage, andSendEventDataBatch, none of which exist on the current surface.samples/README.mdfromEVENTHUBS_CONNECTION_STRINGtoEVENTHUB_CONNECTION_STRING, which is the name that the sample code andci.ymluse.EntityPath precedence
The behavior matches .NET. An empty
eventHubparameter adopts theEntityPathvalue, a matching value passes, and a different value throwsstd::invalid_argument.ServiceBusSasConnectionStringCredentialalready 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.
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 theEVENTHUB_CONSUMER_GROUPenvironment variable, on this branch and onmain. That behavior predates this change, and this change does not touch the checkpoint store.Work not done in this pull request
test-resources.jsonsets"disableLocalAuth": trueon 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 restoredConnectionStringparameterizations stay dormant until the environment variable exists.connection_string_credential.cppbuilds for both backends, so CI should cover this.BlobCheckpointStorekeeps its current surface. It takes aBlobContainerClient, and Azure Storage already shipsBlobContainerClient::CreateFromConnectionString, so a connection string user has a path with no new API.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.