Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eh named key #18292

Merged
merged 36 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7f70520
Add AzureNamedKeyCredential
rakshith91 Mar 24, 2021
3db2ef2
lint
rakshith91 Mar 25, 2021
be51628
Merge branch 'master' into named_key
Mar 25, 2021
87530e9
Update sdk/core/azure-core/CHANGELOG.md
Mar 26, 2021
8be7ce5
some changes
rakshith91 Apr 14, 2021
8b21514
oops
rakshith91 Apr 14, 2021
75ecf46
Merge branch 'master' into named_key
Apr 14, 2021
05c4205
version
rakshith91 Apr 14, 2021
d8ba6de
mypy fix
rakshith91 Apr 14, 2021
1555f1d
lint
rakshith91 Apr 15, 2021
6ab090c
remove policy
rakshith91 Apr 16, 2021
6a98f0b
doc
rakshith91 Apr 16, 2021
5f94691
Update sdk/core/azure-core/azure/core/pipeline/policies/_authenticati…
Apr 16, 2021
53fab2e
Update sdk/core/azure-core/azure/core/pipeline/policies/__init__.py
Apr 16, 2021
0865f90
Update sdk/core/azure-core/azure/core/pipeline/policies/__init__.py
Apr 16, 2021
4a6736f
changelog
rakshith91 Apr 16, 2021
4c2143d
update tests
rakshith91 Apr 16, 2021
71f0b35
fix
rakshith91 Apr 16, 2021
845c6cb
base
rakshith91 Apr 21, 2021
574f3bc
add nk cred
rakshith91 Apr 21, 2021
4e2426a
Merge remote-tracking branch 'upstream/master' into eh_named_key
rakshith91 Apr 29, 2021
34a3a65
fix merge
rakshith91 Apr 29, 2021
8e559a5
Update sdk/eventhub/azure-eventhub/CHANGELOG.md
Apr 29, 2021
9ebe8b5
named key
rakshith91 Apr 29, 2021
e23f2d6
Apply suggestions from code review
Apr 29, 2021
27d80e2
update test
rakshith91 Apr 30, 2021
005af59
analyze
rakshith91 Apr 30, 2021
cd0cc62
lint
rakshith91 Apr 30, 2021
31b279d
lint
rakshith91 Apr 30, 2021
3c13677
mypy
rakshith91 Apr 30, 2021
c85e5c2
Update sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_aut…
Apr 30, 2021
9455bd2
Update sdk/eventhub/azure-eventhub/samples/async_samples/authenticate…
Apr 30, 2021
dd9ea6c
Apply suggestions from code review
May 3, 2021
b73b419
rename
rakshith91 May 4, 2021
77e90d9
Update sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_as…
May 4, 2021
ee9548d
ops
rakshith91 May 4, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion sdk/eventhub/azure-eventhub/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Release History

## 5.4.1 (Unreleased)
## 5.5.0 (Unreleased)

**New Features**
- Added support for using `azure.core.credentials.AzureNamedKeyCredential` as credential for authenticating producer and consumer clients.

rakshith91 marked this conversation as resolved.
Show resolved Hide resolved
**Notes**

- Updated azure-core dependency to 1.14.0.

**Bug Fixes**

Expand Down
25 changes: 23 additions & 2 deletions sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@

from uamqp import AMQPClient, Message, authentication, constants, errors, compat, utils
import six
from azure.core.credentials import AccessToken, AzureSasCredential, AzureNamedKeyCredential
from azure.core.utils import parse_connection_string as core_parse_connection_string
from azure.core.credentials import AccessToken, AzureSasCredential


from .exceptions import _handle_exception, ClientClosedError, ConnectError
from ._configuration import Configuration
Expand Down Expand Up @@ -173,6 +174,24 @@ 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):
yunhaoling marked this conversation as resolved.
Show resolved Hide resolved
"""The named key credential used for authentication.

:param str credential: The AzureNamedKeyCredential that should be used
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved
"""

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)
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved


class EventHubSASTokenCredential(object):
"""The shared access token credential used for authentication.
Expand Down Expand Up @@ -226,7 +245,7 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument

class ClientBase(object): # pylint:disable=too-many-instance-attributes
def __init__(self, fully_qualified_namespace, eventhub_name, credential, **kwargs):
# type: (str, str, Union[AzureSasCredential, TokenCredential], Any) -> None
# type: (str, str, Union[AzureSasCredential, TokenCredential, AzureNamedKeyCredential], Any) -> None
self.eventhub_name = eventhub_name
if not eventhub_name:
raise ValueError("The eventhub name can not be None or empty.")
Expand All @@ -235,6 +254,8 @@ def __init__(self, fully_qualified_namespace, eventhub_name, credential, **kwarg
self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8]
if isinstance(credential, AzureSasCredential):
self._credential = AzureSasTokenCredential(credential)
elif isinstance(credential, AzureNamedKeyCredential):
self._credential = AzureNamedKeyTokenCredential(credential) # type: ignore
yunhaoling marked this conversation as resolved.
Show resolved Hide resolved
else:
self._credential = credential #type: ignore
self._keep_alive = kwargs.get("keep_alive", 30)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

if TYPE_CHECKING:
import datetime
from azure.core.credentials import TokenCredential, AzureSasCredential
from azure.core.credentials import TokenCredential, AzureSasCredential, AzureNamedKeyCredential
from typing import ( # pylint: disable=ungrouped-imports
Any,
Union,
Expand Down Expand Up @@ -59,6 +59,7 @@ class EventHubConsumerClient(ClientBase):
:class:`EventHubSharedKeyCredential<azure.eventhub.EventHubSharedKeyCredential>`, or credential objects generated
by the azure-identity library and objects that implement the `get_token(self, *scopes)` method.
: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 float auth_timeout: The time in seconds to wait for a token to be authorized by the service.
The default value is 60 seconds. If set to 0, no timeout will be enforced from the client.
Expand Down Expand Up @@ -129,7 +130,7 @@ def __init__(
fully_qualified_namespace, # type: str
eventhub_name, # type: str
consumer_group, # type: str
credential, # type: Union[AzureSasCredential, TokenCredential]
credential, # type: Union[AzureSasCredential, TokenCredential, AzureNamedKeyCredential]
**kwargs # type: Any
):
# type: (...) -> None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from ._common import EventDataBatch, EventData

if TYPE_CHECKING:
from azure.core.credentials import TokenCredential, AzureSasCredential
from azure.core.credentials import TokenCredential, AzureSasCredential, AzureNamedKeyCredential

_LOGGER = logging.getLogger(__name__)

Expand All @@ -33,6 +33,7 @@ class EventHubProducerClient(ClientBase):
:class:`EventHubSharedKeyCredential<azure.eventhub.EventHubSharedKeyCredential>`, or credential objects generated
by the azure-identity library and objects that implement the `get_token(self, *scopes)` method.
: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 float auth_timeout: The time in seconds to wait for a token to be authorized by the service.
The default value is 60 seconds. If set to 0, no timeout will be enforced from the client.
Expand Down Expand Up @@ -74,7 +75,7 @@ def __init__(
self,
fully_qualified_namespace, # type: str
eventhub_name, # type: str
credential, # type: Union[AzureSasCredential, TokenCredential]
credential, # type: Union[AzureSasCredential, TokenCredential, AzureNamedKeyCredential]
**kwargs # type: Any
):
# type:(...) -> None
Expand Down
2 changes: 1 addition & 1 deletion sdk/eventhub/azure-eventhub/azure/eventhub/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
# Licensed under the MIT License.
# ------------------------------------

VERSION = "5.4.1"
VERSION = "5.5.0"
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Message,
AMQPClientAsync,
)
from azure.core.credentials import AccessToken, AzureSasCredential
from azure.core.credentials import AccessToken, AzureSasCredential, AzureNamedKeyCredential

from .._client_base import ClientBase, _generate_sas_token, _parse_conn_str
from .._utils import utc_from_timestamp, parse_sas_credential
Expand Down Expand Up @@ -83,6 +83,24 @@ async def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken: # pylint
"""
return AccessToken(self.token, self.expiry)

class AzureNamedKeyTokenCredentialAsync(object):
"""The named key credential used for authentication.

:param str credential: The AzureNamedKeyCredential that should be used
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved
"""

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)
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved


class AzureSasTokenCredentialAsync(object):
"""The shared access token credential used for authentication
when AzureSasCredential is provided.
Expand All @@ -107,12 +125,14 @@ def __init__(
self,
fully_qualified_namespace: str,
eventhub_name: str,
credential: Union["AsyncTokenCredential", AzureSasCredential],
credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential],
**kwargs: Any
) -> None:
self._loop = kwargs.pop("loop", None)
if isinstance(credential, AzureSasCredential):
self._credential = AzureSasTokenCredentialAsync(credential) # type: ignore
elif isinstance(credential, AzureNamedKeyCredential):
self._credential = AzureNamedKeyTokenCredentialAsync(credential) # type: ignore
yunhaoling marked this conversation as resolved.
Show resolved Hide resolved
else:
self._credential = credential # type: ignore
super(ClientBaseAsync, self).__init__(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Awaitable,
)

from azure.core.credentials import AzureSasCredential
from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential

from ._eventprocessor.event_processor import EventProcessor
from ._consumer_async import EventHubConsumer
Expand Down Expand Up @@ -66,6 +66,7 @@ class EventHubConsumerClient(ClientBaseAsync):
:class:`EventHubSharedKeyCredential<azure.eventhub.aio.EventHubSharedKeyCredential>`, or credential objects
generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method.
:type credential: ~azure.core.credentials_async.AsyncTokenCredential or ~azure.core.credentials.AzureSasCredential
or ~azure.core.credentials.AzureNamedKeyCredential
swathipil marked this conversation as resolved.
Show resolved Hide resolved
:keyword bool logging_enable: Whether to output network trace logs to the logger. Default is `False`.
:keyword float auth_timeout: The time in seconds to wait for a token to be authorized by the service.
The default value is 60 seconds. If set to 0, no timeout will be enforced from the client.
Expand Down Expand Up @@ -136,7 +137,7 @@ def __init__(
fully_qualified_namespace: str,
eventhub_name: str,
consumer_group: str,
credential: Union["AsyncTokenCredential", AzureSasCredential],
credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential],
**kwargs
) -> None:
self._checkpoint_store = kwargs.pop("checkpoint_store", None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, Union, TYPE_CHECKING, List, Optional, Dict, cast
from uamqp import constants

from azure.core.credentials import AzureSasCredential
from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential

from ..exceptions import ConnectError, EventHubError
from ._client_base_async import ClientBaseAsync
Expand Down Expand Up @@ -36,6 +36,7 @@ class EventHubProducerClient(ClientBaseAsync):
:class:`EventHubSharedKeyCredential<azure.eventhub.aio.EventHubSharedKeyCredential>`, or credential objects
generated by the azure-identity library and objects that implement the `get_token(self, *scopes)` method.
: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 float auth_timeout: The time in seconds to wait for a token to be authorized by the service.
The default value is 60 seconds. If set to 0, no timeout will be enforced from the client.
Expand Down Expand Up @@ -76,7 +77,7 @@ def __init__(
self,
fully_qualified_namespace: str,
eventhub_name: str,
credential: Union["AsyncTokenCredential", AzureSasCredential],
credential: Union["AsyncTokenCredential", AzureSasCredential, AzureNamedKeyCredential],
**kwargs
) -> None:
super(EventHubProducerClient, self).__init__(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/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.
# --------------------------------------------------------------------------------------------

"""
Example to demonstrate utilizing AzureNamedKeyCredential to authenticate with Event Hubs.
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved
"""

# pylint: disable=C0111

import os
import time
from azure.core.credentials import AzureNamedKeyCredential
swathipil marked this conversation as resolved.
Show resolved Hide resolved
from azure.eventhub.aio import EventHubProducerClient
from azure.eventhub import EventData

# Target namespace and hub must also be specified.
FULLY_QUALIFIED_NAMESPACE = os.environ['EVENT_HUB_HOSTNAME']
EVENTHUB_NAME = os.environ['EVENT_HUB_NAME']

EVENTHUB_POLICY_NAME = os.environ['EVENT_HUB_POLICY_NAME']
EVENTHUB_KEY = os.environ['EVENT_HUB_KEY']
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved

credential = AzureNamedKeyCredential(EVENTHUB_POLICY_NAME, EVENTHUB_KEY)

producer_client = EventHubProducerClient(
fully_qualified_namespace=FULLY_QUALIFIED_NAMESPACE,
eventhub_name=EVENTHUB_NAME,
credential=credential,
logging_enable=True
)

start_time = time.time()
async def authenticate_with_named_key():
async with producer_client:
event_data_batch = await producer_client.create_batch()
event_data_batch.add(EventData('Single message'))
await producer_client.send_batch(event_data_batch)

loop = asyncio.get_event_loop()
start_time = time.time()
loop.run_until_complete(authenticate_with_named_key())
print("Send messages in {} seconds.".format(time.time() - start_time))
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/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.
# --------------------------------------------------------------------------------------------

"""
Example to demonstrate utilizing AzureNamedKeyCredential to authenticate with Event Hubs.
"""

# pylint: disable=C0111

import os
import time
from azure.core.credentials import AzureNamedKeyCredential
swathipil marked this conversation as resolved.
Show resolved Hide resolved
from azure.eventhub import EventHubProducerClient, EventData

# Target namespace and hub must also be specified.
FULLY_QUALIFIED_NAMESPACE = os.environ['EVENT_HUB_HOSTNAME']
EVENTHUB_NAME = os.environ['EVENT_HUB_NAME']

EVENTHUB_POLICY_NAME = os.environ['EVENT_HUB_POLICY_NAME']
EVENTHUB_KEY = os.environ['EVENT_HUB_KEY']
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved

credential = AzureNamedKeyCredential(EVENTHUB_POLICY_NAME, EVENTHUB_KEY)

producer_client = EventHubProducerClient(
fully_qualified_namespace=FULLY_QUALIFIED_NAMESPACE,
eventhub_name=EVENTHUB_NAME,
credential=credential,
logging_enable=True
)

start_time = time.time()
with producer_client:
event_data_batch = producer_client.create_batch()
event_data_batch.add(EventData('Single message'))
producer_client.send_batch(event_data_batch)

print("Send messages in {} seconds.".format(time.time() - start_time))
2 changes: 1 addition & 1 deletion sdk/eventhub/azure-eventhub/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
zip_safe=False,
packages=find_packages(exclude=exclude_packages),
install_requires=[
"azure-core<2.0.0,>=1.13.0",
"azure-core<2.0.0,>=1.14.0",
"uamqp>=1.3.0,<2.0.0",
],
extras_require={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import datetime
import time

from azure.core.credentials import AzureSasCredential
from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential
from azure.identity.aio import EnvironmentCredential
from azure.eventhub import EventData
from azure.eventhub.aio import EventHubConsumerClient, EventHubProducerClient, EventHubSharedKeyCredential
Expand Down Expand Up @@ -133,3 +133,24 @@ async def test_client_azure_sas_credential_async(self,
batch = await producer_client.create_batch(partition_id='0')
batch.add(EventData(body='A single message'))
await producer_client.send_batch(batch)

@pytest.mark.liveTest
@pytest.mark.asyncio
async def test_client_azure_named_key_credential_async(live_eventhub):

hostname = "{}.servicebus.windows.net".format(eventhub_namespace.name)
rakshith91 marked this conversation as resolved.
Show resolved Hide resolved
consumer_client = EventHubConsumerClient(fully_qualified_namespace=live_eventhub['hostname'],
eventhub_name=live_eventhub['event_hub'],
consumer_group='$default',
credential=credential,
swathipil marked this conversation as resolved.
Show resolved Hide resolved
user_agent='customized information')

assert (await consumer_client.get_eventhub_properties()) is not None

credential.update("foo", "bar")

with pytest.raises(Exception):
await consumer_client.get_eventhub_properties()

credential.update(live_eventhub['key_name'], live_eventhub['access_key'])
assert (await consumer_client.get_eventhub_properties()) is not None
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from azure.identity import EnvironmentCredential
from azure.eventhub import EventData, EventHubProducerClient, EventHubConsumerClient, EventHubSharedKeyCredential
from azure.eventhub._client_base import EventHubSASTokenCredential
from azure.core.credentials import AzureSasCredential
from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential

@pytest.mark.liveTest
def test_client_secret_credential(live_eventhub):
Expand Down Expand Up @@ -107,3 +107,22 @@ def test_client_azure_sas_credential(live_eventhub):
batch = producer_client.create_batch(partition_id='0')
batch.add(EventData(body='A single message'))
producer_client.send_batch(batch)

@pytest.mark.liveTest
def test_client_azure_named_key_credential(live_eventhub):
credential = AzureNamedKeyCredential(live_eventhub['key_name'], live_eventhub['access_key'])
consumer_client = EventHubConsumerClient(fully_qualified_namespace=live_eventhub['hostname'],
eventhub_name=live_eventhub['event_hub'],
consumer_group='$default',
credential=credential,
swathipil marked this conversation as resolved.
Show resolved Hide resolved
user_agent='customized information')

assert consumer_client.get_eventhub_properties() is not None

credential.update("foo", "bar")

with pytest.raises(Exception):
consumer_client.get_eventhub_properties()

credential.update(live_eventhub['key_name'], live_eventhub['access_key'])
assert consumer_client.get_eventhub_properties() is not None
Loading