From a9919bea8e1b64d9e860906aee00d8af6b1f34a2 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 30 Apr 2021 17:06:47 -0700 Subject: [PATCH 1/7] Service Bus Named Key Credential --- sdk/servicebus/azure-servicebus/CHANGELOG.md | 5 +++ .../azure/servicebus/_base_handler.py | 22 ++++++++++-- .../azure/servicebus/_servicebus_client.py | 5 +-- .../azure/servicebus/_servicebus_receiver.py | 5 +-- .../azure/servicebus/_servicebus_sender.py | 5 +-- .../servicebus/aio/_base_handler_async.py | 22 ++++++++++-- .../aio/_servicebus_client_async.py | 5 +-- .../aio/_servicebus_receiver_async.py | 5 +-- .../aio/_servicebus_sender_async.py | 5 +-- sdk/servicebus/azure-servicebus/setup.py | 2 +- .../tests/async_tests/test_sb_client_async.py | 34 ++++++++++++++++++- .../azure-servicebus/tests/test_sb_client.py | 34 +++++++++++++++++-- shared_requirements.txt | 2 +- 13 files changed, 130 insertions(+), 21 deletions(-) diff --git a/sdk/servicebus/azure-servicebus/CHANGELOG.md b/sdk/servicebus/azure-servicebus/CHANGELOG.md index a10a14ccccca..2479f23173ac 100644 --- a/sdk/servicebus/azure-servicebus/CHANGELOG.md +++ b/sdk/servicebus/azure-servicebus/CHANGELOG.md @@ -6,8 +6,13 @@ The preview features related to AMQPAnnotatedMessage introduced in 7.2.0b1 are n **New Features** +* Added support for using `azure.core.credentials.AzureNamedKeyCredential` as credential for authenticating the clients. * Support for using `azure.core.credentials.AzureSasCredential` as credential for authenticating the clients is now GA. +**Notes** + +* Updated azure-core dependency to 1.14.0. + ## 7.2.0b1 (2021-04-07) **New Features** diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py index 2c8e17a0e68f..0fd100bfe493 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py @@ -19,7 +19,7 @@ from uamqp import utils, compat from uamqp.message import MessageProperties -from azure.core.credentials import AccessToken, AzureSasCredential +from azure.core.credentials import AccessToken, AzureSasCredential, AzureNamedKeyCredential from ._common._configuration import Configuration from .exceptions import ( @@ -196,6 +196,22 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument raise ValueError("No token scope provided.") return _generate_sas_token(scopes[0], self.policy, self.key) +class AzureNamedKeyTokenCredential(object): + """The named key credential used for authentication. + :param str credential: The AzureNamedKeyCredential that should be used + """ + + def __init__(self, credential): + # type: (AzureNamedKeyCredential) -> None + self.credential = credential + self.token_type = b"servicebus.windows.net:sastoken" + + def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument + # type: (str, Any) -> _AccessToken + if not scopes: + raise ValueError("No token scope provided.") + name, key = self.credential.named_key + return _generate_sas_token(scopes[0], name, key) class ServiceBusAzureSasCredential(object): """The shared access token credential used for authentication @@ -219,7 +235,7 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument class BaseHandler: # pylint:disable=too-many-instance-attributes def __init__(self, fully_qualified_namespace, entity_name, credential, **kwargs): - # type: (str, str, Union[TokenCredential, AzureSasCredential], Any) -> None + # type: (str, str, Union[TokenCredential, AzureSasCredential, AzureNamedKeyCredential], Any) -> None # If the user provided http:// or sb://, let's be polite and strip that. self.fully_qualified_namespace = strip_protocol_from_uri( fully_qualified_namespace.strip() @@ -233,6 +249,8 @@ def __init__(self, fully_qualified_namespace, entity_name, credential, **kwargs) self._mgmt_target = "{}{}".format(self._entity_path, MANAGEMENT_PATH_SUFFIX) if isinstance(credential, AzureSasCredential): self._credential = ServiceBusAzureSasCredential(credential) + elif isinstance(credential, AzureNamedKeyCredential): + self._credential = AzureNamedKeyTokenCredential(credential) # type: ignore else: self._credential = credential # type: ignore self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8] diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_client.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_client.py index f124a6a71eba..79cd76996abe 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_client.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_client.py @@ -24,7 +24,7 @@ from ._common.constants import ServiceBusSubQueue if TYPE_CHECKING: - from azure.core.credentials import TokenCredential, AzureSasCredential + from azure.core.credentials import TokenCredential, AzureSasCredential, AzureNamedKeyCredential _LOGGER = logging.getLogger(__name__) @@ -44,6 +44,7 @@ class ServiceBusClient(object): credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword bool logging_enable: Whether to output network trace logs to the logger. Default is `False`. :keyword transport_type: The type of transport protocol that will be used for communicating with the Service Bus service. Default is `TransportType.Amqp` in which case port 5671 is used. @@ -72,7 +73,7 @@ class ServiceBusClient(object): """ def __init__(self, fully_qualified_namespace, credential, **kwargs): - # type: (str, Union[TokenCredential, AzureSasCredential], Any) -> None + # type: (str, Union[TokenCredential, AzureSasCredential, AzureNamedKeyCredential], Any) -> None # If the user provided http:// or sb://, let's be polite and strip that. self.fully_qualified_namespace = strip_protocol_from_uri( fully_qualified_namespace.strip() diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_receiver.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_receiver.py index 0df9db5bd7b5..5ff3019bea2c 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_receiver.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_receiver.py @@ -55,7 +55,7 @@ if TYPE_CHECKING: import datetime - from azure.core.credentials import TokenCredential, AzureSasCredential + from azure.core.credentials import TokenCredential, AzureSasCredential, AzureNamedKeyCredential _LOGGER = logging.getLogger(__name__) @@ -85,6 +85,7 @@ class ServiceBusReceiver( credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword str queue_name: The path of specific Service Bus Queue the client connects to. :keyword str topic_name: The path of specific Service Bus Topic which contains the Subscription the client connects to. @@ -120,7 +121,7 @@ class ServiceBusReceiver( """ def __init__(self, fully_qualified_namespace, credential, **kwargs): - # type: (str, Union[TokenCredential, AzureSasCredential], Any) -> None + # type: (str, Union[TokenCredential, AzureSasCredential, AzureNamedKeyCredential], Any) -> None self._message_iter = None # type: Optional[Iterator[ServiceBusReceivedMessage]] if kwargs.get("entity_name"): super(ServiceBusReceiver, self).__init__( diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py index 5b13d39d2bbf..623a855ea213 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_servicebus_sender.py @@ -39,7 +39,7 @@ if TYPE_CHECKING: import datetime - from azure.core.credentials import TokenCredential, AzureSasCredential + from azure.core.credentials import TokenCredential, AzureSasCredential, AzureNamedKeyCredential MessageTypes = Union[ Mapping[str, Any], @@ -130,6 +130,7 @@ class ServiceBusSender(BaseHandler, SenderMixin): credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials.TokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword str queue_name: The path of specific Service Bus Queue the client connects to. :keyword str topic_name: The path of specific Service Bus Topic the client connects to. :keyword bool logging_enable: Whether to output network trace logs to the logger. Default is `False`. @@ -143,7 +144,7 @@ class ServiceBusSender(BaseHandler, SenderMixin): """ def __init__(self, fully_qualified_namespace, credential, **kwargs): - # type: (str, Union[TokenCredential, AzureSasCredential], Any) -> None + # type: (str, Union[TokenCredential, AzureSasCredential, AzureNamedKeyCredential], Any) -> None if kwargs.get("entity_name"): super(ServiceBusSender, self).__init__( fully_qualified_namespace=fully_qualified_namespace, diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py index ffa386cbdd83..23593ff807ab 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py @@ -12,7 +12,7 @@ from uamqp import compat from uamqp.message import MessageProperties -from azure.core.credentials import AccessToken, AzureSasCredential +from azure.core.credentials import AccessToken, AzureSasCredential, AzureNamedKeyCredential from .._base_handler import _generate_sas_token, BaseHandler as BaseHandlerSync from .._common._configuration import Configuration @@ -80,6 +80,22 @@ async def get_token( raise ValueError("No token scope provided.") return _generate_sas_token(scopes[0], self.policy, self.key) +class AzureNamedKeyTokenCredentialAsync(object): + """The named key credential used for authentication. + :param str credential: The AzureNamedKeyCredential that should be used + """ + + def __init__(self, credential): + # type: (AzureNamedKeyCredential) -> None + self.credential = credential + self.token_type = b"servicebus.windows.net:sastoken" + + async def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument + if not scopes: + raise ValueError("No token scope provided.") + name, key = self.credential.named_key + return _generate_sas_token(scopes[0], name, key) + class ServiceBusAzureSasCredentialAsync(object): """The shared access token credential used for authentication @@ -104,7 +120,7 @@ def __init__( self, fully_qualified_namespace: str, entity_name: str, - credential: Union["AsyncTokenCredential", AzureSasCredential], + credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential], **kwargs: Any ) -> None: # If the user provided http:// or sb://, let's be polite and strip that. @@ -120,6 +136,8 @@ def __init__( self._mgmt_target = "{}{}".format(self._entity_path, MANAGEMENT_PATH_SUFFIX) if isinstance(credential, AzureSasCredential): self._credential = ServiceBusAzureSasCredentialAsync(credential) + elif isinstance(credential, AzureNamedKeyCredential): + self._credential = AzureNamedKeyTokenCredentialAsync(credential) # type: ignore else: self._credential = credential # type: ignore self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8] diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_client_async.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_client_async.py index bcdf51457820..5be437a0452a 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_client_async.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_client_async.py @@ -6,7 +6,7 @@ import logging import uamqp -from azure.core.credentials import AzureSasCredential +from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential from .._base_handler import _parse_conn_str from ._base_handler_async import ( @@ -42,6 +42,7 @@ class ServiceBusClient(object): credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword bool logging_enable: Whether to output network trace logs to the logger. Default is `False`. :keyword transport_type: The type of transport protocol that will be used for communicating with the Service Bus service. Default is `TransportType.Amqp` in which case port 5671 is used. @@ -72,7 +73,7 @@ class ServiceBusClient(object): def __init__( self, fully_qualified_namespace: str, - credential: Union["AsyncTokenCredential", AzureSasCredential], + credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential], **kwargs: Any ) -> None: # If the user provided http:// or sb://, let's be polite and strip that. diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_receiver_async.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_receiver_async.py index 77d9ce7d98c5..c3f5785fd774 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_receiver_async.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_receiver_async.py @@ -13,7 +13,7 @@ from uamqp import ReceiveClientAsync, types, Message from uamqp.constants import SenderSettleMode -from azure.core.credentials import AzureSasCredential +from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential from ..exceptions import ServiceBusError from ._servicebus_session_async import ServiceBusSession @@ -82,6 +82,7 @@ class ServiceBusReceiver(collections.abc.AsyncIterator, BaseHandler, ReceiverMix credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword str queue_name: The path of specific Service Bus Queue the client connects to. :keyword str topic_name: The path of specific Service Bus Topic which contains the Subscription the client connects to. @@ -119,7 +120,7 @@ class ServiceBusReceiver(collections.abc.AsyncIterator, BaseHandler, ReceiverMix def __init__( self, fully_qualified_namespace: str, - credential: Union["AsyncTokenCredential", AzureSasCredential], + credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential], **kwargs: Any ) -> None: self._message_iter = ( diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_sender_async.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_sender_async.py index 3210ec2373b0..3d4f2a4a79cf 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_sender_async.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_servicebus_sender_async.py @@ -9,7 +9,7 @@ import uamqp from uamqp import SendClientAsync, types -from azure.core.credentials import AzureSasCredential +from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential from .._common.message import ServiceBusMessage, ServiceBusMessageBatch from .._servicebus_sender import SenderMixin @@ -66,6 +66,7 @@ class ServiceBusSender(BaseHandler, SenderMixin): credential objects generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method, or alternatively, an AzureSasCredential can be provided too. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureSasCredential + or ~azure.core.credentials.AzureNamedKeyCredential :keyword str queue_name: The path of specific Service Bus Queue the client connects to. Only one of queue_name or topic_name can be provided. :keyword str topic_name: The path of specific Service Bus Topic the client connects to. @@ -83,7 +84,7 @@ class ServiceBusSender(BaseHandler, SenderMixin): def __init__( self, fully_qualified_namespace: str, - credential: Union["AsyncTokenCredential", AzureSasCredential], + credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential], **kwargs: Any ) -> None: if kwargs.get("entity_name"): diff --git a/sdk/servicebus/azure-servicebus/setup.py b/sdk/servicebus/azure-servicebus/setup.py index 3b2039ccc2ee..f3a5e64f6df7 100644 --- a/sdk/servicebus/azure-servicebus/setup.py +++ b/sdk/servicebus/azure-servicebus/setup.py @@ -82,7 +82,7 @@ "uamqp>=1.3.0,<2.0.0", 'azure-common~=1.1', 'msrest>=0.6.17,<2.0.0', - 'azure-core<2.0.0,>=1.13.0', + 'azure-core<2.0.0,>=1.14.0', "isodate>=0.6.0", "six>=1.11.0", ], diff --git a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py index 29de2f6b52fb..3a9039e0561f 100644 --- a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py +++ b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py @@ -8,7 +8,7 @@ import logging import pytest -from azure.core.credentials import AzureSasCredential +from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential from azure.mgmt.servicebus.models import AccessRights from azure.servicebus.aio import ServiceBusClient, ServiceBusSender, ServiceBusReceiver from azure.servicebus import ServiceBusMessage @@ -320,3 +320,35 @@ async def test_client_azure_sas_credential_async(self, assert len(client._handlers) == 0 async with client.get_queue_sender(servicebus_queue.name) as sender: await sender.send_messages(ServiceBusMessage("foo")) + + @pytest.mark.liveTest + @pytest.mark.live_test_only + @CachedResourceGroupPreparer() + @CachedServiceBusNamespacePreparer(name_prefix='servicebustest') + @CachedServiceBusQueuePreparer(name_prefix='servicebustest') + async def test_client_named_key_credential_async(self, + servicebus_queue, + servicebus_namespace, + servicebus_namespace_key_name, + servicebus_namespace_primary_key, + servicebus_namespace_connection_string, + **kwargs): + hostname = "{}.servicebus.windows.net".format(servicebus_namespace.name) + credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + + client = ServiceBusClient(hostname, credential) + async with client: + async with client.get_queue_sender(servicebus_queue.name) as sender: + await sender.send_messages(ServiceBusMessage("foo")) + + credential.update("foo", "bar") + async with pytest.raises(Exception): + async with client: + async with client.get_queue_sender(servicebus_queue.name) as sender: + await sender.send_messages(ServiceBusMessage("foo")) + + # update back to the right key again + credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + async with client: + async with client.get_queue_sender(servicebus_queue.name) as sender: + await sender.send_messages(ServiceBusMessage("foo")) diff --git a/sdk/servicebus/azure-servicebus/tests/test_sb_client.py b/sdk/servicebus/azure-servicebus/tests/test_sb_client.py index 6f7550156e2a..6447d7486300 100644 --- a/sdk/servicebus/azure-servicebus/tests/test_sb_client.py +++ b/sdk/servicebus/azure-servicebus/tests/test_sb_client.py @@ -12,7 +12,7 @@ from datetime import datetime, timedelta from azure.common import AzureHttpError, AzureConflictHttpError -from azure.core.credentials import AzureSasCredential +from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential from azure.mgmt.servicebus.models import AccessRights from azure.servicebus import ServiceBusClient, ServiceBusSender, ServiceBusReceiver from azure.servicebus._base_handler import ServiceBusSharedKeyCredential @@ -319,7 +319,7 @@ def test_client_credential(self, @CachedResourceGroupPreparer() @CachedServiceBusNamespacePreparer(name_prefix='servicebustest') @CachedServiceBusQueuePreparer(name_prefix='servicebustest') - def test_client_azure_sas_credential(self, + def test_client_azure_named_key_credential(self, servicebus_queue, servicebus_namespace, servicebus_namespace_key_name, @@ -338,5 +338,35 @@ def test_client_azure_sas_credential(self, client = ServiceBusClient(hostname, credential) with client: assert len(client._handlers) == 0 + + @pytest.mark.liveTest + @pytest.mark.live_test_only + @CachedResourceGroupPreparer() + @CachedServiceBusNamespacePreparer(name_prefix='servicebustest') + @CachedServiceBusQueuePreparer(name_prefix='servicebustest') + def test_client_azure_named_key_credential(self, + servicebus_queue, + servicebus_namespace, + servicebus_namespace_key_name, + servicebus_namespace_primary_key, + servicebus_namespace_connection_string, + **kwargs): + hostname = "{}.servicebus.windows.net".format(servicebus_namespace.name) + credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + + client = ServiceBusClient(hostname, credential) + with client: + with client.get_queue_sender(servicebus_queue.name) as sender: + sender.send_messages(ServiceBusMessage("foo")) + + credential.update("foo", "bar") + with pytest.raises(Exception): + with client: + with client.get_queue_sender(servicebus_queue.name) as sender: + sender.send_messages(ServiceBusMessage("foo")) + + # update back to the right key again + credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + with client: with client.get_queue_sender(servicebus_queue.name) as sender: sender.send_messages(ServiceBusMessage("foo")) diff --git a/shared_requirements.txt b/shared_requirements.txt index b5df03e3402d..8a477b6ee3c4 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -173,7 +173,7 @@ opentelemetry-sdk<2.0.0,>=1.0.0 #override azure-appconfiguration msrest>=0.6.10 #override azure-servicebus uamqp>=1.3.0,<2.0.0 #override azure-servicebus msrest>=0.6.17,<2.0.0 -#override azure-servicebus azure-core<2.0.0,>=1.13.0 +#override azure-servicebus azure-core<2.0.0,>=1.14.0 #override azure-search-documents msrest>=0.6.21 #override azure-synapse-accesscontrol azure-core>=1.6.0,<2.0.0 #override azure-synapse-spark azure-core>=1.6.0,<2.0.0 From bde65583437ab9597cf094fe01ca002ae3d72485 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 00:10:18 -0700 Subject: [PATCH 2/7] Update sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py --- .../azure-servicebus/azure/servicebus/_base_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py index 0fd100bfe493..cc467c9c5668 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py @@ -207,7 +207,7 @@ def __init__(self, credential): self.token_type = b"servicebus.windows.net:sastoken" def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument - # type: (str, Any) -> _AccessToken + # type: (str, Any) -> AccessToken if not scopes: raise ValueError("No token scope provided.") name, key = self.credential.named_key From 200b00fd4cc0b0e47a0fd6113a26fbc5f7fac637 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 19:02:23 -0700 Subject: [PATCH 3/7] improvements --- .../azure/servicebus/_base_handler.py | 13 +++++++------ .../azure/servicebus/aio/_base_handler_async.py | 13 +++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py index cc467c9c5668..5b41690b0dc7 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/_base_handler.py @@ -196,21 +196,22 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument raise ValueError("No token scope provided.") return _generate_sas_token(scopes[0], self.policy, self.key) -class AzureNamedKeyTokenCredential(object): +class ServiceBusAzureNamedKeyTokenCredential(object): """The named key credential used for authentication. - :param str credential: The AzureNamedKeyCredential that should be used + :param credential: The AzureNamedKeyCredential that should be used. + :type credential: ~azure.core.credentials.AzureNamedKeyCredential """ - def __init__(self, credential): + def __init__(self, azure_named_key_credential): # type: (AzureNamedKeyCredential) -> None - self.credential = credential + self._credential = azure_named_key_credential self.token_type = b"servicebus.windows.net:sastoken" def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument # type: (str, Any) -> AccessToken if not scopes: raise ValueError("No token scope provided.") - name, key = self.credential.named_key + name, key = self._credential.named_key return _generate_sas_token(scopes[0], name, key) class ServiceBusAzureSasCredential(object): @@ -250,7 +251,7 @@ def __init__(self, fully_qualified_namespace, entity_name, credential, **kwargs) if isinstance(credential, AzureSasCredential): self._credential = ServiceBusAzureSasCredential(credential) elif isinstance(credential, AzureNamedKeyCredential): - self._credential = AzureNamedKeyTokenCredential(credential) # type: ignore + self._credential = ServiceBusAzureNamedKeyTokenCredential(credential) # type: ignore else: self._credential = credential # type: ignore self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8] diff --git a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py index 23593ff807ab..a1e124f2c2ff 100644 --- a/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py +++ b/sdk/servicebus/azure-servicebus/azure/servicebus/aio/_base_handler_async.py @@ -80,20 +80,21 @@ async def get_token( raise ValueError("No token scope provided.") return _generate_sas_token(scopes[0], self.policy, self.key) -class AzureNamedKeyTokenCredentialAsync(object): +class ServiceBusAzureNamedKeyTokenCredentialAsync(object): """The named key credential used for authentication. - :param str credential: The AzureNamedKeyCredential that should be used + :param credential: The AzureNamedKeyCredential that should be used. + :type credential: ~azure.core.credentials.AzureNamedKeyCredential """ - def __init__(self, credential): + def __init__(self, azure_named_key_credential): # type: (AzureNamedKeyCredential) -> None - self.credential = credential + self._credential = azure_named_key_credential self.token_type = b"servicebus.windows.net:sastoken" async def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument if not scopes: raise ValueError("No token scope provided.") - name, key = self.credential.named_key + name, key = self._credential.named_key return _generate_sas_token(scopes[0], name, key) @@ -137,7 +138,7 @@ def __init__( if isinstance(credential, AzureSasCredential): self._credential = ServiceBusAzureSasCredentialAsync(credential) elif isinstance(credential, AzureNamedKeyCredential): - self._credential = AzureNamedKeyTokenCredentialAsync(credential) # type: ignore + self._credential = ServiceBusAzureNamedKeyTokenCredentialAsync(credential) # type: ignore else: self._credential = credential # type: ignore self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8] From 747e0a68fb4b12c88e2d2c5ab320a2fdacd0c97e Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 19:16:13 -0700 Subject: [PATCH 4/7] add samples --- ...authenticate_using_named_key_credential.py | 33 +++++++++++++++++++ ...authenticate_using_named_key_credential.py | 27 +++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py create mode 100644 sdk/servicebus/azure-servicebus/samples/sync_samples/authenticate_using_named_key_credential.py diff --git a/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py b/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py new file mode 100644 index 000000000000..a03b8fab1189 --- /dev/null +++ b/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +""" +An example to show authentication using AzureNamedKeyCredential. +""" + +import os +import asyncio +from azure.core.credentials import AzureNamedKeyCredential +from azure.servicebus.aio import ServiceBusClient +from azure.servicebus import ServiceBusMessage + + +FULLY_QUALIFIED_NAMESPACE = os.environ['SERVICE_BUS_FULLY_QUALIFIED_NAMESPACE'] +QUEUE_NAME = os.environ["SERVICE_BUS_QUEUE_NAME"] +SAS_POLICY = os.environ['SERVICE_BUS_SAS_POLICY'] +SERVICEBUS_SAS_KEY = os.environ['SERVICE_BUS_SAS_KEY'] + + +credential = AzureNamedKeyCredential(SAS_POLICY, SERVICEBUS_SAS_KEY) + +async def send_message(): + async with ServiceBusClient(FULLY_QUALIFIED_NAMESPACE, credential) as client: + async with client.get_queue_sender(QUEUE_NAME) as sender: + await sender.send_messages([ServiceBusMessage("hello")]) + +loop = asyncio.get_event_loop() +start_time = time.time() +loop.run_until_complete(send_message()) diff --git a/sdk/servicebus/azure-servicebus/samples/sync_samples/authenticate_using_named_key_credential.py b/sdk/servicebus/azure-servicebus/samples/sync_samples/authenticate_using_named_key_credential.py new file mode 100644 index 000000000000..2d5d41f27383 --- /dev/null +++ b/sdk/servicebus/azure-servicebus/samples/sync_samples/authenticate_using_named_key_credential.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +""" +An example to show authentication using AzureNamedKeyCredential. +""" + +import os + +from azure.core.credentials import AzureNamedKeyCredential +from azure.servicebus import ServiceBusClient, ServiceBusMessage + + +FULLY_QUALIFIED_NAMESPACE = os.environ['SERVICE_BUS_FULLY_QUALIFIED_NAMESPACE'] +QUEUE_NAME = os.environ["SERVICE_BUS_QUEUE_NAME"] +SAS_POLICY = os.environ['SERVICE_BUS_SAS_POLICY'] +SERVICEBUS_SAS_KEY = os.environ['SERVICE_BUS_SAS_KEY'] + + +credential = AzureNamedKeyCredential(SAS_POLICY, SERVICEBUS_SAS_KEY) + +with ServiceBusClient(FULLY_QUALIFIED_NAMESPACE, credential) as client: + with client.get_queue_sender(QUEUE_NAME) as sender: + sender.send_messages([ServiceBusMessage("hello")]) From 4ce8ff7492fe2f4ffd93431bda073299cf58cb4f Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Tue, 4 May 2021 01:06:29 -0700 Subject: [PATCH 5/7] update tests --- .../tests/async_tests/test_sb_client_async.py | 4 ++-- sdk/servicebus/azure-servicebus/tests/test_sb_client.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py index 3a9039e0561f..9ba977b8bf4a 100644 --- a/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py +++ b/sdk/servicebus/azure-servicebus/tests/async_tests/test_sb_client_async.py @@ -342,13 +342,13 @@ async def test_client_named_key_credential_async(self, await sender.send_messages(ServiceBusMessage("foo")) credential.update("foo", "bar") - async with pytest.raises(Exception): + with pytest.raises(Exception): async with client: async with client.get_queue_sender(servicebus_queue.name) as sender: await sender.send_messages(ServiceBusMessage("foo")) # update back to the right key again - credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + credential.update(servicebus_namespace_key_name, servicebus_namespace_primary_key) async with client: async with client.get_queue_sender(servicebus_queue.name) as sender: await sender.send_messages(ServiceBusMessage("foo")) diff --git a/sdk/servicebus/azure-servicebus/tests/test_sb_client.py b/sdk/servicebus/azure-servicebus/tests/test_sb_client.py index 6447d7486300..7a945818533a 100644 --- a/sdk/servicebus/azure-servicebus/tests/test_sb_client.py +++ b/sdk/servicebus/azure-servicebus/tests/test_sb_client.py @@ -366,7 +366,7 @@ def test_client_azure_named_key_credential(self, sender.send_messages(ServiceBusMessage("foo")) # update back to the right key again - credential = AzureNamedKeyCredential(servicebus_namespace_key_name, servicebus_namespace_primary_key) + credential.update(servicebus_namespace_key_name, servicebus_namespace_primary_key) with client: with client.get_queue_sender(servicebus_queue.name) as sender: sender.send_messages(ServiceBusMessage("foo")) From 14f7ddbc1d0b38b8f2fae01fa6bb8cf89565336c Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Tue, 4 May 2021 08:36:29 -0700 Subject: [PATCH 6/7] rename --- ...ential.py => authenticate_using_named_key_credential_async.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sdk/servicebus/azure-servicebus/samples/async_samples/{authenticate_using_named_key_credential.py => authenticate_using_named_key_credential_async.py} (100%) diff --git a/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py b/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py similarity index 100% rename from sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential.py rename to sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py From e315bbc0e20f204996875ef0d51c6233fa56ab0a Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Tue, 4 May 2021 11:31:43 -0700 Subject: [PATCH 7/7] oops --- .../authenticate_using_named_key_credential_async.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py b/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py index a03b8fab1189..e135fae3edf5 100644 --- a/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py +++ b/sdk/servicebus/azure-servicebus/samples/async_samples/authenticate_using_named_key_credential_async.py @@ -29,5 +29,4 @@ async def send_message(): await sender.send_messages([ServiceBusMessage("hello")]) loop = asyncio.get_event_loop() -start_time = time.time() loop.run_until_complete(send_message())