Skip to content

Commit e6f98bc

Browse files
authored
[Event Hubs] Update URI used for consumer auth to include consumer group (#35626)
* add consumer group to uri used for consumer auth * changelog * add consumergroup to auth uri for consumer ops only, not mgmt ops * lint * fix sample
1 parent 61138a7 commit e6f98bc

File tree

8 files changed

+32
-19
lines changed

8 files changed

+32
-19
lines changed

sdk/eventhub/azure-eventhub/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- Fixed a bug where the correct URI was not being used for consumer authentication, causing issues when assigning roles at the consumer group level. ([#35337](https://github.com/Azure/azure-sdk-for-python/issues/35337))
12+
1113
### Other Changes
1214

1315
## 5.12.0 (2024-05-16)

sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ def __init__(
318318
else:
319319
self._credential = credential # type: ignore
320320
self._auto_reconnect = kwargs.get("auto_reconnect", True)
321-
self._auth_uri = f"sb://{self._address.hostname}{self._address.path}"
321+
self._auth_uri: str
322+
self._eventhub_auth_uri = f"sb://{self._address.hostname}{self._address.path}"
322323
self._config = Configuration(
323324
amqp_transport=self._amqp_transport,
324325
hostname=self._address.hostname,
@@ -348,29 +349,32 @@ def _from_connection_string(conn_str: str, **kwargs: Any) -> Dict[str, Any]:
348349
kwargs["credential"] = EventHubSharedKeyCredential(policy, key)
349350
return kwargs
350351

351-
def _create_auth(self) -> Union["uamqp_JWTTokenAuth", JWTTokenAuth]:
352+
def _create_auth(self, *, auth_uri: Optional[str] = None) -> Union["uamqp_JWTTokenAuth", JWTTokenAuth]:
352353
"""
353354
Create an ~uamqp.authentication.SASTokenAuth instance
354355
to authenticate the session.
355356
356357
:return: The auth for the session.
357358
:rtype: JWTTokenAuth or uamqp_JWTTokenAuth
358359
"""
360+
# if auth_uri is not provided, use the default hub one
361+
entity_auth_uri = auth_uri if auth_uri else self._eventhub_auth_uri
362+
359363
try:
360364
# ignore mypy's warning because token_type is Optional
361365
token_type = self._credential.token_type # type: ignore
362366
except AttributeError:
363367
token_type = b"jwt"
364368
if token_type == b"servicebus.windows.net:sastoken":
365369
return self._amqp_transport.create_token_auth(
366-
self._auth_uri,
367-
functools.partial(self._credential.get_token, self._auth_uri),
370+
entity_auth_uri,
371+
functools.partial(self._credential.get_token, entity_auth_uri),
368372
token_type=token_type,
369373
config=self._config,
370374
update_token=True,
371375
)
372376
return self._amqp_transport.create_token_auth(
373-
self._auth_uri,
377+
entity_auth_uri,
374378
functools.partial(self._credential.get_token, JWT_TOKEN_SCOPE),
375379
token_type=token_type,
376380
config=self._config,
@@ -563,7 +567,7 @@ def _open(self) -> bool:
563567
if not self.running:
564568
if self._handler:
565569
self._handler.close()
566-
auth = self._client._create_auth()
570+
auth = self._client._create_auth(auth_uri=self._client._auth_uri)
567571
self._create_handler(auth)
568572
conn = self._client._conn_manager.get_connection( # pylint: disable=protected-access
569573
endpoint=self._client._address.hostname, auth=auth

sdk/eventhub/azure-eventhub/azure/eventhub/_consumer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def _open(self) -> bool:
200200
if not self.running:
201201
if self._handler:
202202
self._handler.close()
203-
auth = self._client._create_auth()
203+
auth = self._client._create_auth(auth_uri=self._client._auth_uri)
204204
self._create_handler(auth)
205205
conn = self._client._conn_manager.get_connection( # pylint: disable=protected-access
206206
endpoint=self._client._address.hostname, auth=auth

sdk/eventhub/azure-eventhub/azure/eventhub/_consumer_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ def __init__(
178178
network_tracing=network_tracing,
179179
**kwargs
180180
)
181+
# consumer auth URI additionally includes consumer group
182+
self._auth_uri = f"sb://{self._address.hostname}{self._address.path}/consumergroups/{self._consumer_group}"
181183
self._lock = threading.Lock()
182184
self._event_processors: Dict[Tuple[str, str], EventProcessor] = {}
183185

sdk/eventhub/azure-eventhub/azure/eventhub/_producer_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def __init__(
201201
network_tracing=kwargs.get("logging_enable"),
202202
**kwargs
203203
)
204-
204+
self._auth_uri = f"sb://{self._address.hostname}{self._address.path}"
205205
self._keep_alive = kwargs.get("keep_alive", None)
206206

207207
self._producers: Dict[str, Optional[EventHubProducer]] = {

sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,14 @@
4646
from .._pyamqp.aio._authentication_async import JWTTokenAuthAsync
4747
try:
4848
from uamqp import (
49-
authentication as uamqp_authentication,
5049
Message as uamqp_Message,
5150
AMQPClientAsync as uamqp_AMQPClientAsync,
5251
)
53-
from uamqp.authentication import JWTTokenAsync
52+
from uamqp.authentication import JWTTokenAsync as uamqp_JWTTokenAsync
5453
except ImportError:
55-
uamqp_authentication = None
5654
uamqp_Message = None
5755
uamqp_AMQPClientAsync = None
58-
JWTTokenAsync = None
56+
uamqp_JWTTokenAsync = None
5957
from azure.core.credentials_async import AsyncTokenCredential
6058

6159
try:
@@ -109,7 +107,7 @@ def running(self) -> bool:
109107
def running(self, value: bool) -> None:
110108
pass
111109

112-
def _create_handler(self, auth: Union["JWTTokenAsync", JWTTokenAuthAsync]) -> None:
110+
def _create_handler(self, auth: Union["uamqp_JWTTokenAsync", JWTTokenAuthAsync]) -> None:
113111
pass
114112

115113
_MIXIN_BASE = AbstractConsumerProducer
@@ -268,30 +266,34 @@ def _from_connection_string(conn_str: str, **kwargs) -> Dict[str, Any]:
268266
kwargs["credential"] = EventHubSharedKeyCredential(policy, key)
269267
return kwargs
270268

271-
async def _create_auth_async(self) -> Union[uamqp_authentication.JWTTokenAsync, JWTTokenAuthAsync]:
269+
async def _create_auth_async(
270+
self, *, auth_uri: Optional[str] = None
271+
) -> Union["uamqp_JWTTokenAsync", JWTTokenAuthAsync]:
272272
"""
273273
Create an ~uamqp.authentication.SASTokenAuthAsync instance to authenticate
274274
the session.
275275
276276
:return: A JWTTokenAuthAsync instance to authenticate the session.
277277
:rtype: ~uamqp.authentication.JWTTokenAsync or JWTTokenAuthAsync
278-
279278
"""
279+
# if auth_uri is not provided, use the default hub one
280+
entity_auth_uri = auth_uri if auth_uri else self._eventhub_auth_uri
281+
280282
try:
281283
# ignore mypy's warning because token_type is Optional
282284
token_type = self._credential.token_type # type: ignore
283285
except AttributeError:
284286
token_type = b"jwt"
285287
if token_type == b"servicebus.windows.net:sastoken":
286288
return await self._amqp_transport.create_token_auth_async(
287-
self._auth_uri,
288-
functools.partial(self._credential.get_token, self._auth_uri),
289+
entity_auth_uri,
290+
functools.partial(self._credential.get_token, entity_auth_uri),
289291
token_type=token_type,
290292
config=self._config,
291293
update_token=True,
292294
)
293295
return await self._amqp_transport.create_token_auth_async(
294-
self._auth_uri,
296+
entity_auth_uri,
295297
functools.partial(self._credential.get_token, JWT_TOKEN_SCOPE),
296298
token_type=token_type,
297299
config=self._config,
@@ -475,7 +477,7 @@ async def _open(self) -> None:
475477
if not self.running:
476478
if self._handler:
477479
await self._handler.close_async()
478-
auth = await self._client._create_auth_async()
480+
auth = await self._client._create_auth_async(auth_uri=self._client._auth_uri)
479481
self._create_handler(auth)
480482
conn = await self._client._conn_manager_async.get_connection(
481483
endpoint=self._client._address.hostname, auth=auth

sdk/eventhub/azure-eventhub/azure/eventhub/aio/_consumer_client_async.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ def __init__(
191191
network_tracing=network_tracing,
192192
**kwargs,
193193
)
194+
# consumer auth URI additionally includes consumer group
195+
self._auth_uri = f"sb://{self._address.hostname}{self._address.path}/consumergroups/{self._consumer_group}"
194196
self._lock = asyncio.Lock(**self._internal_kwargs)
195197
self._event_processors: Dict[Tuple[str, str], EventProcessor] = {}
196198

sdk/eventhub/azure-eventhub/azure/eventhub/aio/_producer_client_async.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ def __init__(
188188
network_tracing=kwargs.pop("logging_enable", False),
189189
**kwargs
190190
)
191+
self._auth_uri = f"sb://{self._address.hostname}{self._address.path}"
191192
self._keep_alive = kwargs.get("keep_alive", None)
192193
self._producers: Dict[str, Optional[EventHubProducer]] = {
193194
ALL_PARTITIONS: self._create_producer()

0 commit comments

Comments
 (0)