From 7f705208687be4ab9399cf82d89312094daca896 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 24 Mar 2021 15:55:00 -0700 Subject: [PATCH 01/33] Add AzureNamedKeyCredential --- sdk/core/azure-core/CHANGELOG.md | 6 ++- sdk/core/azure-core/azure/core/_version.py | 2 +- sdk/core/azure-core/azure/core/credentials.py | 48 ++++++++++++++++++- .../azure/core/pipeline/policies/__init__.py | 3 +- .../core/pipeline/policies/_authentication.py | 17 +++++++ .../azure-core/tests/test_authentication.py | 45 ++++++++++++++++- 6 files changed, 115 insertions(+), 6 deletions(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index cac731af04f0..2d5f7500018b 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -1,6 +1,10 @@ # Release History -## 1.12.1 (Unreleased) +## 1.13.0 (Unreleased) + +### Features + +- Added `azure.core.credentials.AzureNamedKeyCredential` credential. ### Bug fixes diff --git a/sdk/core/azure-core/azure/core/_version.py b/sdk/core/azure-core/azure/core/_version.py index e89e943b0813..7a5c38e4c326 100644 --- a/sdk/core/azure-core/azure/core/_version.py +++ b/sdk/core/azure-core/azure/core/_version.py @@ -9,4 +9,4 @@ # regenerated. # -------------------------------------------------------------------------- -VERSION = "1.12.1" +VERSION = "1.13.0" diff --git a/sdk/core/azure-core/azure/core/credentials.py b/sdk/core/azure-core/azure/core/credentials.py index 21aeb433ac81..00319b94b875 100644 --- a/sdk/core/azure-core/azure/core/credentials.py +++ b/sdk/core/azure-core/azure/core/credentials.py @@ -30,7 +30,7 @@ def get_token(self, *scopes, **kwargs): AccessToken = namedtuple("AccessToken", ["token", "expires_on"]) -__all__ = ["AzureKeyCredential", "AzureSasCredential", "AccessToken"] +__all__ = ["AzureKeyCredential", "AzureSasCredential", "AccessToken", "AzureNamedKeyCredential"] class AzureKeyCredential(object): @@ -111,3 +111,49 @@ def update(self, signature): if not isinstance(signature, six.string_types): raise TypeError("The signature used for updating must be a string.") self._signature = signature + + +class AzureNamedKeyCredential(object): + """Credential type used for working with any service needing a named key that follows patterns + established by the other credential types. + + :param str name: The name of the credential used to authenticate to an Azure service. + :param str key: The key used to authenticate to an Azure service. + :raises: TypeError + """ + def __init__(self, name, key): + # type: (str, str) -> None + if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): + raise TypeError("Both name and key must be Strings.") + self._name = name + self._key = key + + @property + def name(self): + # type () -> str + """The value of the configured name. + + :rtype: str + """ + return self._name + + @property + def key(self): + # type () -> str + """The value of the configured key. + + :rtype: str + """ + return self._key + + def update(self, name, key): + # type: (str, str) -> None + """Update the named key credential. + + Both name and key must be provided in order to update the named key credential. + Individual attributes cannot be updated. + """ + if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): + raise TypeError("Both name and key must be Strings.") + self._name = name + self._key = key diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py index a0e81b13cef5..74079e477ccd 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py @@ -25,7 +25,7 @@ # -------------------------------------------------------------------------- from ._base import HTTPPolicy, SansIOHTTPPolicy, RequestHistory -from ._authentication import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy +from ._authentication import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy, AzureNamedKeyCredentialPolicy from ._custom_hook import CustomHookPolicy from ._redirect import RedirectPolicy from ._retry import RetryPolicy, RetryMode @@ -45,6 +45,7 @@ 'SansIOHTTPPolicy', 'BearerTokenCredentialPolicy', 'AzureKeyCredentialPolicy', + 'AzureNamedKeyCredentialPolicy', 'AzureSasCredentialPolicy', 'HeadersPolicy', 'UserAgentPolicy', diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index 929920033cdf..14feb08f0e3e 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -145,3 +145,20 @@ def on_request(self, request): else: url = url + "?" + signature request.http_request.url = url + + +class AzureNamedKeyCredentialPolicy(SansIOHTTPPolicy): + """Adds a key header for the provided credential. + + :param credential: The credential used to authenticate requests. + :type credential: ~azure.core.credentials.AzureNamedKeyCredential + :raises: ValueError or TypeError + """ + def __init__(self, credential, **kwargs): # pylint: disable=unused-argument + # type: (AzureNamedKeyCredential, **Any) -> None + super(AzureNamedKeyCredentialPolicy, self).__init__() + self._key = credential.key + self._name = credential.name + + def on_request(self, request): + request.http_request.headers[self._name] = self._key diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index ddfcc314fcd9..c8a8af6fb800 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -6,10 +6,13 @@ import time import azure.core -from azure.core.credentials import AccessToken, AzureKeyCredential, AzureSasCredential +from azure.core.credentials import AccessToken, AzureKeyCredential, AzureSasCredential, AzureNamedKeyCredential from azure.core.exceptions import ServiceRequestError from azure.core.pipeline import Pipeline -from azure.core.pipeline.policies import BearerTokenCredentialPolicy, SansIOHTTPPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy +from azure.core.pipeline.policies import ( + BearerTokenCredentialPolicy, SansIOHTTPPolicy, AzureKeyCredentialPolicy, + AzureSasCredentialPolicy, AzureNamedKeyCredentialPolicy +) from azure.core.pipeline.transport import HttpRequest import pytest @@ -230,3 +233,41 @@ def test_azure_sas_credential_policy_raises(): sas = 1234 with pytest.raises(TypeError): credential = AzureSasCredential(sas) + +def test_azure_named_key_credential(): + cred = AzureNamedKeyCredential("sample_name", "samplekey") + + assert cred.name == "sample_name" + assert cred.key == "samplekey" + + cred.update("newname", "newkey") + assert cred.name == "newname" + assert cred.key == "newkey" + + +def test_azure_named_key_credential_raises(): + with pytest.raises(TypeError, match="Both name and key must be Strings."): + cred = AzureNamedKeyCredential("sample_name", 123345) + + cred = AzureNamedKeyCredential("sample_name", "samplekey") + assert cred.name == "sample_name" + assert cred.key == "samplekey" + + with pytest.raises(TypeError, match="Both name and key must be Strings."): + cred.update(1234, "newkey") + +def test_azure_named_key_credential_policy(): + """Tests to see if we can create an AzureKeyCredentialPolicy""" + + key_name = "api_key" + api_key = "test_key" + + def verify_authorization_header(request): + assert request.headers[key_name] == api_key + + transport=Mock(send=verify_authorization_header) + credential = AzureNamedKeyCredential(key_name, api_key) + credential_policy = AzureNamedKeyCredentialPolicy(credential=credential) + pipeline = Pipeline(transport=transport, policies=[credential_policy]) + + pipeline.run(HttpRequest("GET", "https://test_key_credential")) From 3db2ef26ec7e3ffb25b5cfc9d3c693ad6615e095 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 24 Mar 2021 17:12:43 -0700 Subject: [PATCH 02/33] lint --- .../azure-core/azure/core/pipeline/policies/__init__.py | 5 ++++- .../azure/core/pipeline/policies/_authentication.py | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py index 74079e477ccd..a3aa02dd03f1 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py @@ -25,7 +25,10 @@ # -------------------------------------------------------------------------- from ._base import HTTPPolicy, SansIOHTTPPolicy, RequestHistory -from ._authentication import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy, AzureNamedKeyCredentialPolicy +from ._authentication import ( + BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy, + AzureNamedKeyCredentialPolicy + ) from ._custom_hook import CustomHookPolicy from ._redirect import RedirectPolicy from ._retry import RetryPolicy, RetryMode diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index 14feb08f0e3e..2c2622899ea5 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -17,7 +17,13 @@ if TYPE_CHECKING: # pylint:disable=unused-import from typing import Any, Dict, Optional - from azure.core.credentials import AccessToken, TokenCredential, AzureKeyCredential, AzureSasCredential + from azure.core.credentials import ( + AccessToken, + TokenCredential, + AzureKeyCredential, + AzureSasCredential, + AzureNamedKeyCredential + ) from azure.core.pipeline import PipelineRequest From 87530e982055b7f8c53856f060238e1e53368c5c Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 26 Mar 2021 09:58:34 -0700 Subject: [PATCH 03/33] Update sdk/core/azure-core/CHANGELOG.md Co-authored-by: swathipil <76007337+swathipil@users.noreply.github.com> --- sdk/core/azure-core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index 1e80588d8282..ce23c8899c8d 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features -- Added `azure.core.credentials.AzureNamedKeyCredential` credential #17548. +- Added `azure.core.credentials.AzureNamedKeyCredential` credential and its respective policy #17548. - Supported adding custom policies #16519 ### Bug fixes From 8be7ce5f3bc763abdbedf15855e1b524c521dcfd Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 14 Apr 2021 15:46:01 -0700 Subject: [PATCH 04/33] some changes --- sdk/core/azure-core/azure/core/credentials.py | 25 ++++++------------- .../core/pipeline/policies/_authentication.py | 8 +++--- .../azure-core/tests/test_authentication.py | 14 +++++------ .../azure/eventgrid/_helpers.py | 5 ++++ 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/sdk/core/azure-core/azure/core/credentials.py b/sdk/core/azure-core/azure/core/credentials.py index 00319b94b875..5419f5dec7e9 100644 --- a/sdk/core/azure-core/azure/core/credentials.py +++ b/sdk/core/azure-core/azure/core/credentials.py @@ -4,6 +4,7 @@ # license information. # ------------------------------------------------------------------------- from typing import TYPE_CHECKING +from collections import namedtuple import six @@ -26,10 +27,11 @@ def get_token(self, *scopes, **kwargs): else: - from collections import namedtuple - AccessToken = namedtuple("AccessToken", ["token", "expires_on"]) +AzureNamedKey = namedtuple("AzureNamedKey", ["name", "key"]) + + __all__ = ["AzureKeyCredential", "AzureSasCredential", "AccessToken", "AzureNamedKeyCredential"] @@ -125,26 +127,16 @@ def __init__(self, name, key): # type: (str, str) -> None if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): raise TypeError("Both name and key must be Strings.") - self._name = name - self._key = key + self._credential = AzureNamedKey(name, key) @property - def name(self): + def credential(self): # type () -> str """The value of the configured name. :rtype: str """ - return self._name - - @property - def key(self): - # type () -> str - """The value of the configured key. - - :rtype: str - """ - return self._key + return self._credential def update(self, name, key): # type: (str, str) -> None @@ -155,5 +147,4 @@ def update(self, name, key): """ if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): raise TypeError("Both name and key must be Strings.") - self._name = name - self._key = key + self._credential = AzureNamedKey(name, key) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index 2c2622899ea5..df7bdd050a3b 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -160,11 +160,11 @@ class AzureNamedKeyCredentialPolicy(SansIOHTTPPolicy): :type credential: ~azure.core.credentials.AzureNamedKeyCredential :raises: ValueError or TypeError """ - def __init__(self, credential, **kwargs): # pylint: disable=unused-argument + def __init__(self, credential, name, **kwargs): # pylint: disable=unused-argument # type: (AzureNamedKeyCredential, **Any) -> None super(AzureNamedKeyCredentialPolicy, self).__init__() - self._key = credential.key - self._name = credential.name + self._credential = credential + self._name = name def on_request(self, request): - request.http_request.headers[self._name] = self._key + request.http_request.headers[self._name] = self._credential.credential.key diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index c8a8af6fb800..e1bf5ef2b980 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -237,12 +237,12 @@ def test_azure_sas_credential_policy_raises(): def test_azure_named_key_credential(): cred = AzureNamedKeyCredential("sample_name", "samplekey") - assert cred.name == "sample_name" - assert cred.key == "samplekey" + assert cred.credential.name == "sample_name" + assert cred.credential.key == "samplekey" cred.update("newname", "newkey") - assert cred.name == "newname" - assert cred.key == "newkey" + assert cred.credential.name == "newname" + assert cred.credential.key == "newkey" def test_azure_named_key_credential_raises(): @@ -250,8 +250,8 @@ def test_azure_named_key_credential_raises(): cred = AzureNamedKeyCredential("sample_name", 123345) cred = AzureNamedKeyCredential("sample_name", "samplekey") - assert cred.name == "sample_name" - assert cred.key == "samplekey" + assert cred.credential.name == "sample_name" + assert cred.credential.key == "samplekey" with pytest.raises(TypeError, match="Both name and key must be Strings."): cred.update(1234, "newkey") @@ -267,7 +267,7 @@ def verify_authorization_header(request): transport=Mock(send=verify_authorization_header) credential = AzureNamedKeyCredential(key_name, api_key) - credential_policy = AzureNamedKeyCredentialPolicy(credential=credential) + credential_policy = AzureNamedKeyCredentialPolicy(credential=credential, name=key_name) pipeline = Pipeline(transport=transport, policies=[credential_policy]) pipeline.run(HttpRequest("GET", "https://test_key_credential")) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py index bc7b15bf089f..486036ab6a34 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py @@ -77,6 +77,11 @@ def _get_authentication_policy(credential): return AzureKeyCredentialPolicy( credential=credential, name=constants.EVENTGRID_KEY_HEADER ) + elif isinstance(credential, AzureNamedKeyCredential): + return AzureNamedKeyCredentialPolicy( + name=constants.EVENTGRID_KEY_HEADER, + credential=credential + ) if isinstance(credential, AzureSasCredential): return EventGridSasCredentialPolicy( credential=credential, name=constants.EVENTGRID_TOKEN_HEADER From 8b215145a62806dd897488ff040e3738bf36b479 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 14 Apr 2021 15:47:30 -0700 Subject: [PATCH 05/33] oops --- sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py index 486036ab6a34..bc7b15bf089f 100644 --- a/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py +++ b/sdk/eventgrid/azure-eventgrid/azure/eventgrid/_helpers.py @@ -77,11 +77,6 @@ def _get_authentication_policy(credential): return AzureKeyCredentialPolicy( credential=credential, name=constants.EVENTGRID_KEY_HEADER ) - elif isinstance(credential, AzureNamedKeyCredential): - return AzureNamedKeyCredentialPolicy( - name=constants.EVENTGRID_KEY_HEADER, - credential=credential - ) if isinstance(credential, AzureSasCredential): return EventGridSasCredentialPolicy( credential=credential, name=constants.EVENTGRID_TOKEN_HEADER From 05c4205d4dee9e16d6bb4ee11174eb86286b741d Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 14 Apr 2021 15:51:25 -0700 Subject: [PATCH 06/33] version --- sdk/core/azure-core/azure/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/azure/core/_version.py b/sdk/core/azure-core/azure/core/_version.py index 36514ce9837d..656148f88d2b 100644 --- a/sdk/core/azure-core/azure/core/_version.py +++ b/sdk/core/azure-core/azure/core/_version.py @@ -9,4 +9,4 @@ # regenerated. # -------------------------------------------------------------------------- -VERSION = "1.13.1" +VERSION = "1.14.0" From d8ba6de40fa26ae762461f944764be6d807cde21 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 14 Apr 2021 16:10:18 -0700 Subject: [PATCH 07/33] mypy fix --- .../azure-core/azure/core/pipeline/policies/_authentication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index df7bdd050a3b..9285179304fa 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -161,7 +161,7 @@ class AzureNamedKeyCredentialPolicy(SansIOHTTPPolicy): :raises: ValueError or TypeError """ def __init__(self, credential, name, **kwargs): # pylint: disable=unused-argument - # type: (AzureNamedKeyCredential, **Any) -> None + # type: (AzureNamedKeyCredential, str, **Any) -> None super(AzureNamedKeyCredentialPolicy, self).__init__() self._credential = credential self._name = name From 1555f1df063e17ab4c3fb10522f6de076d30dc01 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 14 Apr 2021 18:07:09 -0700 Subject: [PATCH 08/33] lint --- sdk/core/azure-core/azure/core/credentials.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/core/azure-core/azure/core/credentials.py b/sdk/core/azure-core/azure/core/credentials.py index 5419f5dec7e9..da83603cf8bf 100644 --- a/sdk/core/azure-core/azure/core/credentials.py +++ b/sdk/core/azure-core/azure/core/credentials.py @@ -3,11 +3,10 @@ # Licensed under the MIT License. See LICENSE.txt in the project root for # license information. # ------------------------------------------------------------------------- -from typing import TYPE_CHECKING from collections import namedtuple +from typing import TYPE_CHECKING import six - if TYPE_CHECKING: from typing import Any, NamedTuple from typing_extensions import Protocol From 6ab090c75eb2baf874e949fd425646c9cbfb333b Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 10:50:21 -0700 Subject: [PATCH 09/33] remove policy --- sdk/core/azure-core/azure/core/credentials.py | 10 +++++----- .../core/pipeline/policies/_authentication.py | 18 ------------------ .../azure-core/tests/test_authentication.py | 18 +----------------- 3 files changed, 6 insertions(+), 40 deletions(-) diff --git a/sdk/core/azure-core/azure/core/credentials.py b/sdk/core/azure-core/azure/core/credentials.py index da83603cf8bf..3c70983d2b3d 100644 --- a/sdk/core/azure-core/azure/core/credentials.py +++ b/sdk/core/azure-core/azure/core/credentials.py @@ -125,15 +125,15 @@ class AzureNamedKeyCredential(object): def __init__(self, name, key): # type: (str, str) -> None if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): - raise TypeError("Both name and key must be Strings.") + raise TypeError("Both name and key must be strings.") self._credential = AzureNamedKey(name, key) @property - def credential(self): - # type () -> str + def named_key(self): + # type () -> AzureNamedKey """The value of the configured name. - :rtype: str + :rtype: AzureNamedKey """ return self._credential @@ -145,5 +145,5 @@ def update(self, name, key): Individual attributes cannot be updated. """ if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): - raise TypeError("Both name and key must be Strings.") + raise TypeError("Both name and key must be strings.") self._credential = AzureNamedKey(name, key) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index 9285179304fa..4e9c8bd47b48 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -22,7 +22,6 @@ TokenCredential, AzureKeyCredential, AzureSasCredential, - AzureNamedKeyCredential ) from azure.core.pipeline import PipelineRequest @@ -151,20 +150,3 @@ def on_request(self, request): else: url = url + "?" + signature request.http_request.url = url - - -class AzureNamedKeyCredentialPolicy(SansIOHTTPPolicy): - """Adds a key header for the provided credential. - - :param credential: The credential used to authenticate requests. - :type credential: ~azure.core.credentials.AzureNamedKeyCredential - :raises: ValueError or TypeError - """ - def __init__(self, credential, name, **kwargs): # pylint: disable=unused-argument - # type: (AzureNamedKeyCredential, str, **Any) -> None - super(AzureNamedKeyCredentialPolicy, self).__init__() - self._credential = credential - self._name = name - - def on_request(self, request): - request.http_request.headers[self._name] = self._credential.credential.key diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index e1bf5ef2b980..b83291d51ee0 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -11,7 +11,7 @@ from azure.core.pipeline import Pipeline from azure.core.pipeline.policies import ( BearerTokenCredentialPolicy, SansIOHTTPPolicy, AzureKeyCredentialPolicy, - AzureSasCredentialPolicy, AzureNamedKeyCredentialPolicy + AzureSasCredentialPolicy ) from azure.core.pipeline.transport import HttpRequest @@ -255,19 +255,3 @@ def test_azure_named_key_credential_raises(): with pytest.raises(TypeError, match="Both name and key must be Strings."): cred.update(1234, "newkey") - -def test_azure_named_key_credential_policy(): - """Tests to see if we can create an AzureKeyCredentialPolicy""" - - key_name = "api_key" - api_key = "test_key" - - def verify_authorization_header(request): - assert request.headers[key_name] == api_key - - transport=Mock(send=verify_authorization_header) - credential = AzureNamedKeyCredential(key_name, api_key) - credential_policy = AzureNamedKeyCredentialPolicy(credential=credential, name=key_name) - pipeline = Pipeline(transport=transport, policies=[credential_policy]) - - pipeline.run(HttpRequest("GET", "https://test_key_credential")) From 6a98f0ba60a7acd9c184a378763f40c9ed6d5a62 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 10:51:13 -0700 Subject: [PATCH 10/33] doc --- sdk/core/azure-core/azure/core/credentials.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/core/azure-core/azure/core/credentials.py b/sdk/core/azure-core/azure/core/credentials.py index 3c70983d2b3d..e5146d7f947a 100644 --- a/sdk/core/azure-core/azure/core/credentials.py +++ b/sdk/core/azure-core/azure/core/credentials.py @@ -143,6 +143,9 @@ def update(self, name, key): Both name and key must be provided in order to update the named key credential. Individual attributes cannot be updated. + + :param str name: The name of the credential used to authenticate to an Azure service. + :param str key: The key used to authenticate to an Azure service. """ if not isinstance(name, six.string_types) or not isinstance(key, six.string_types): raise TypeError("Both name and key must be strings.") From 5f94691050c10285f07ded2098cd1f75dbb029a6 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 10:53:06 -0700 Subject: [PATCH 11/33] Update sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py --- .../azure/core/pipeline/policies/_authentication.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py index 4e9c8bd47b48..929920033cdf 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py @@ -17,12 +17,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import from typing import Any, Dict, Optional - from azure.core.credentials import ( - AccessToken, - TokenCredential, - AzureKeyCredential, - AzureSasCredential, - ) + from azure.core.credentials import AccessToken, TokenCredential, AzureKeyCredential, AzureSasCredential from azure.core.pipeline import PipelineRequest From 53fab2e65909ca8f613768b92033608b22a45ecf Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 10:55:43 -0700 Subject: [PATCH 12/33] Update sdk/core/azure-core/azure/core/pipeline/policies/__init__.py --- sdk/core/azure-core/azure/core/pipeline/policies/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py index a3aa02dd03f1..a390ee201ca6 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py @@ -25,10 +25,7 @@ # -------------------------------------------------------------------------- from ._base import HTTPPolicy, SansIOHTTPPolicy, RequestHistory -from ._authentication import ( - BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy, - AzureNamedKeyCredentialPolicy - ) +from ._authentication import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy, AzureSasCredentialPolicy from ._custom_hook import CustomHookPolicy from ._redirect import RedirectPolicy from ._retry import RetryPolicy, RetryMode From 0865f90ccfc25fee2583fe7fccf3c4792129576f Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 10:56:13 -0700 Subject: [PATCH 13/33] Update sdk/core/azure-core/azure/core/pipeline/policies/__init__.py --- sdk/core/azure-core/azure/core/pipeline/policies/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py index a390ee201ca6..a0e81b13cef5 100644 --- a/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py +++ b/sdk/core/azure-core/azure/core/pipeline/policies/__init__.py @@ -45,7 +45,6 @@ 'SansIOHTTPPolicy', 'BearerTokenCredentialPolicy', 'AzureKeyCredentialPolicy', - 'AzureNamedKeyCredentialPolicy', 'AzureSasCredentialPolicy', 'HeadersPolicy', 'UserAgentPolicy', From 4a6736ff9db74c34cab946e9d7940381fa9af5d1 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 11:41:07 -0700 Subject: [PATCH 14/33] changelog --- sdk/core/azure-core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index 65f85132f74b..4f5feaa9a18a 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -4,7 +4,7 @@ ### New Features -- Added `azure.core.credentials.AzureNamedKeyCredential` credential and its respective policy #17548. +- Added `azure.core.credentials.AzureNamedKeyCredential` credential #17548. ## 1.13.0 (2021-04-02) From 4c2143d0b2fbfb1b392aba66d133ba6155297ce8 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 14:28:40 -0700 Subject: [PATCH 15/33] update tests --- sdk/core/azure-core/tests/test_authentication.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index b83291d51ee0..e73fcdeb1b9c 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -237,12 +237,12 @@ def test_azure_sas_credential_policy_raises(): def test_azure_named_key_credential(): cred = AzureNamedKeyCredential("sample_name", "samplekey") - assert cred.credential.name == "sample_name" - assert cred.credential.key == "samplekey" + assert cred.named_key.name == "sample_name" + assert cred.named_key.key == "samplekey" cred.update("newname", "newkey") - assert cred.credential.name == "newname" - assert cred.credential.key == "newkey" + assert cred.named_key.name == "newname" + assert cred.named_key.key == "newkey" def test_azure_named_key_credential_raises(): @@ -250,8 +250,8 @@ def test_azure_named_key_credential_raises(): cred = AzureNamedKeyCredential("sample_name", 123345) cred = AzureNamedKeyCredential("sample_name", "samplekey") - assert cred.credential.name == "sample_name" - assert cred.credential.key == "samplekey" + assert cred.named_key.name == "sample_name" + assert cred.named_key.key == "samplekey" with pytest.raises(TypeError, match="Both name and key must be Strings."): cred.update(1234, "newkey") From 71f0b35d56e7577b1cadf544f33eb609c47647b9 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 16 Apr 2021 15:22:06 -0700 Subject: [PATCH 16/33] fix --- sdk/core/azure-core/tests/test_authentication.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index e73fcdeb1b9c..2bc7555344e6 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -246,12 +246,12 @@ def test_azure_named_key_credential(): def test_azure_named_key_credential_raises(): - with pytest.raises(TypeError, match="Both name and key must be Strings."): + with pytest.raises(TypeError, match="Both name and key must be strings."): cred = AzureNamedKeyCredential("sample_name", 123345) cred = AzureNamedKeyCredential("sample_name", "samplekey") assert cred.named_key.name == "sample_name" assert cred.named_key.key == "samplekey" - with pytest.raises(TypeError, match="Both name and key must be Strings."): + with pytest.raises(TypeError, match="Both name and key must be strings."): cred.update(1234, "newkey") From 845c6cb70819217e7bc6e5b8db6d017dac875110 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Tue, 20 Apr 2021 23:24:10 -0700 Subject: [PATCH 17/33] base --- sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py index b558e173e7ce..65ab1a8aed9a 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py @@ -20,7 +20,7 @@ from uamqp import AMQPClient, Message, authentication, constants, errors, compat, utils import six -from azure.core.credentials import AccessToken, AzureSasCredential +from azure.core.credentials import AccessToken, AzureSasCredential, AzureNamedKeyCredential from .exceptions import _handle_exception, ClientClosedError, ConnectError from ._configuration import Configuration @@ -193,7 +193,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.") @@ -202,6 +202,9 @@ 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): + name, key = credential.named_key + self._credential = EventHubSharedKeyCredential(name, key) else: self._credential = credential #type: ignore self._keep_alive = kwargs.get("keep_alive", 30) From 574f3bcaa74367f72eda3124cd9f468676ee769d Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Wed, 21 Apr 2021 00:13:22 -0700 Subject: [PATCH 18/33] add nk cred --- sdk/eventhub/azure-eventhub/CHANGELOG.md | 4 ++ .../azure/eventhub/_client_base.py | 2 +- .../azure/eventhub/_consumer_client.py | 5 +- .../azure/eventhub/_producer_client.py | 5 +- .../azure/eventhub/aio/_client_base_async.py | 7 ++- .../eventhub/aio/_consumer_client_async.py | 5 +- .../eventhub/aio/_producer_client_async.py | 5 +- ...nticate_with_named_key_credential_async.py | 46 +++++++++++++++++++ .../authenticate_with_named_key_credential.py | 41 +++++++++++++++++ .../livetest/asynctests/test_auth_async.py | 28 ++++++++++- .../tests/livetest/synctests/test_auth.py | 16 ++++++- 11 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py create mode 100644 sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py diff --git a/sdk/eventhub/azure-eventhub/CHANGELOG.md b/sdk/eventhub/azure-eventhub/CHANGELOG.md index b7b15068be25..da43a49ccb6a 100644 --- a/sdk/eventhub/azure-eventhub/CHANGELOG.md +++ b/sdk/eventhub/azure-eventhub/CHANGELOG.md @@ -1,5 +1,9 @@ # Release History +## 5.5.0 (Unreleased) + +- Added support for using `azure.core.credentials.AzureNamedKeyCredential` as credential for authenticating producer and consumer clients. + ## 5.4.0 (2021-04-07) This version follows from version 5.3.1, rather than 5.4.0b1 so that the preview idempotent producer feature is not included. diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py index 65ab1a8aed9a..df5b4c4f3404 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py @@ -204,7 +204,7 @@ def __init__(self, fully_qualified_namespace, eventhub_name, credential, **kwarg self._credential = AzureSasTokenCredential(credential) elif isinstance(credential, AzureNamedKeyCredential): name, key = credential.named_key - self._credential = EventHubSharedKeyCredential(name, key) + self._credential = EventHubSharedKeyCredential(name, key) # type: ignore else: self._credential = credential #type: ignore self._keep_alive = kwargs.get("keep_alive", 30) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_consumer_client.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_consumer_client.py index b8de8ad5ad03..7c05f926d04d 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_consumer_client.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_consumer_client.py @@ -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, @@ -59,6 +59,7 @@ class EventHubConsumerClient(ClientBase): :class:`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. @@ -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 diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_producer_client.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_producer_client.py index b9c40ba804a8..42e8a0d9a443 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_producer_client.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_producer_client.py @@ -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__) @@ -33,6 +33,7 @@ class EventHubProducerClient(ClientBase): :class:`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. @@ -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 diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index d2573480fa61..33831813b246 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -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 @@ -107,12 +107,15 @@ 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): + name, key = credential.named_key + self._credential = EventHubSharedKeyCredential(name, key) # type: ignore else: self._credential = credential # type: ignore super(ClientBaseAsync, self).__init__( diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_consumer_client_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_consumer_client_async.py index 3e95d8384420..4be39f20ae52 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_consumer_client_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_consumer_client_async.py @@ -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 @@ -66,6 +66,7 @@ class EventHubConsumerClient(ClientBaseAsync): :class:`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. @@ -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) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_producer_client_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_producer_client_async.py index fa1c92506099..c540014834f7 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_producer_client_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_producer_client_async.py @@ -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 @@ -36,6 +36,7 @@ class EventHubProducerClient(ClientBaseAsync): :class:`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. @@ -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__( diff --git a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py new file mode 100644 index 000000000000..eb8d84afc140 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py @@ -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. +""" + +# pylint: disable=C0111 + +import os +import time +from azure.core.credentials import AzureNamedKeyCredential +from azure.eventhub.aio import EventHubProducerClient +from azure.eventhub import EventData + +# Target namespace and hub must also be specified. Consumer group is set to default unless required otherwise. +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'] + +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)) diff --git a/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py new file mode 100644 index 000000000000..47b711687609 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py @@ -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 +from azure.eventhub import EventHubProducerClient, EventData + +# Target namespace and hub must also be specified. Consumer group is set to default unless required otherwise. +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'] + +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)) diff --git a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py index bb88e5c2fea8..56254a924f88 100644 --- a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py +++ b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py @@ -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 @@ -133,3 +133,29 @@ 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.live_test_only + @CachedResourceGroupPreparer(name_prefix='eventhubtest') + @CachedEventHubNamespacePreparer(name_prefix='eventhubtest') + @CachedEventHubPreparer(name_prefix='eventhubtest') + async def test_client_azure_sas_credential_async(self, + eventhub, + eventhub_namespace, + eventhub_namespace_key_name, + eventhub_namespace_primary_key, + eventhub_namespace_connection_string, + **kwargs): + + hostname = "{}.servicebus.windows.net".format(eventhub_namespace.name) + producer_client = EventHubProducerClient(fully_qualified_namespace=hostname, + eventhub_name=eventhub.name, + credential=AzureNamedKeyCredential( + eventhub_namespace_key_name, + eventhub_namespace_primary_key + )) + + async with producer_client: + batch = await producer_client.create_batch(partition_id='0') + batch.add(EventData(body='A single message')) + await producer_client.send_batch(batch) \ No newline at end of file diff --git a/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py b/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py index 15b30e938ca8..dd378b196cd0 100644 --- a/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py +++ b/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py @@ -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): @@ -107,3 +107,17 @@ 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): + hostname = live_eventhub['hostname'] + + credential = AzureNamedKeyCredential(live_eventhub['key_name'], live_eventhub['access_key']) + producer_client = EventHubProducerClient(fully_qualified_namespace=hostname, + eventhub_name=live_eventhub['event_hub'], + credential=credential) + + with producer_client: + batch = producer_client.create_batch(partition_id='0') + batch.add(EventData(body='A single message')) + producer_client.send_batch(batch) \ No newline at end of file From 34a3a65fe6797a9d796fe8f08f0cf838bf10428f Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 14:20:23 -0700 Subject: [PATCH 19/33] fix merge --- sdk/core/azure-core/tests/test_authentication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/core/azure-core/tests/test_authentication.py b/sdk/core/azure-core/tests/test_authentication.py index 64da11970fbd..6c112aa5926e 100644 --- a/sdk/core/azure-core/tests/test_authentication.py +++ b/sdk/core/azure-core/tests/test_authentication.py @@ -239,10 +239,12 @@ def test_azure_named_key_credential(): assert cred.named_key.name == "sample_name" assert cred.named_key.key == "samplekey" + assert isinstance(cred.named_key, tuple) cred.update("newname", "newkey") assert cred.named_key.name == "newname" assert cred.named_key.key == "newkey" + assert isinstance(cred.named_key, tuple) def test_azure_named_key_credential_raises(): with pytest.raises(TypeError, match="Both name and key must be strings."): From 8e559a52e970ed2133366779bf44cc59ce3c1363 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 14:20:52 -0700 Subject: [PATCH 20/33] Update sdk/eventhub/azure-eventhub/CHANGELOG.md Co-authored-by: Adam Ling (MSFT) --- sdk/eventhub/azure-eventhub/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sdk/eventhub/azure-eventhub/CHANGELOG.md b/sdk/eventhub/azure-eventhub/CHANGELOG.md index ec936350050c..a7e61021e27c 100644 --- a/sdk/eventhub/azure-eventhub/CHANGELOG.md +++ b/sdk/eventhub/azure-eventhub/CHANGELOG.md @@ -5,6 +5,10 @@ **New Features** - Added support for using `azure.core.credentials.AzureNamedKeyCredential` as credential for authenticating producer and consumer clients. +**Notes** + +- Updated azure-core dependency to 1.14.0. + **Bug Fixes** - Fixed bug that custom user agent string should be put in front of the built-in user agent string instead of being appended. From 9ebe8b55b911f9aea1e23f077bdd1cf11d1a3277 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 15:28:06 -0700 Subject: [PATCH 21/33] named key --- .../azure/eventhub/_client_base.py | 21 ++++++++++++++++-- .../azure/eventhub/aio/_client_base_async.py | 22 +++++++++++++++++-- sdk/eventhub/azure-eventhub/setup.py | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py index 4f646d60e473..16711ccad5f3 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py @@ -174,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): + """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 EventHubSASTokenCredential(object): """The shared access token credential used for authentication. @@ -237,8 +255,7 @@ def __init__(self, fully_qualified_namespace, eventhub_name, credential, **kwarg if isinstance(credential, AzureSasCredential): self._credential = AzureSasTokenCredential(credential) elif isinstance(credential, AzureNamedKeyCredential): - name, key = credential.named_key - self._credential = EventHubSharedKeyCredential(name, key) # type: ignore + self._credential = AzureNamedKeyTokenCredential(credential) # type: ignore else: self._credential = credential #type: ignore self._keep_alive = kwargs.get("keep_alive", 30) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index 054c0d34413d..9cb9e2cb5d1d 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -83,6 +83,25 @@ 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 + """ + + 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 + # 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 AzureSasTokenCredentialAsync(object): """The shared access token credential used for authentication when AzureSasCredential is provided. @@ -114,8 +133,7 @@ def __init__( if isinstance(credential, AzureSasCredential): self._credential = AzureSasTokenCredentialAsync(credential) # type: ignore elif isinstance(credential, AzureNamedKeyCredential): - name, key = credential.named_key - self._credential = EventHubSharedKeyCredential(name, key) # type: ignore + self._credential = AzureNamedKeyTokenCredentialAsync(credential) # type: ignore else: self._credential = credential # type: ignore super(ClientBaseAsync, self).__init__( diff --git a/sdk/eventhub/azure-eventhub/setup.py b/sdk/eventhub/azure-eventhub/setup.py index 8b56a17f4bea..b8c908932b5a 100644 --- a/sdk/eventhub/azure-eventhub/setup.py +++ b/sdk/eventhub/azure-eventhub/setup.py @@ -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={ From e23f2d6297dac6741f1912657e12abe4c072cf38 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 15:29:18 -0700 Subject: [PATCH 22/33] Apply suggestions from code review Co-authored-by: Adam Ling (MSFT) --- .../authenticate_with_named_key_credential_async.py | 2 +- .../sync_samples/authenticate_with_named_key_credential.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py index eb8d84afc140..8dbc44c374ec 100644 --- a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py +++ b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py @@ -17,7 +17,7 @@ from azure.eventhub.aio import EventHubProducerClient from azure.eventhub import EventData -# Target namespace and hub must also be specified. Consumer group is set to default unless required otherwise. +# Target namespace and hub must also be specified. FULLY_QUALIFIED_NAMESPACE = os.environ['EVENT_HUB_HOSTNAME'] EVENTHUB_NAME = os.environ['EVENT_HUB_NAME'] diff --git a/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py index 47b711687609..ab654f37c229 100644 --- a/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py +++ b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py @@ -16,7 +16,7 @@ from azure.core.credentials import AzureNamedKeyCredential from azure.eventhub import EventHubProducerClient, EventData -# Target namespace and hub must also be specified. Consumer group is set to default unless required otherwise. +# Target namespace and hub must also be specified. FULLY_QUALIFIED_NAMESPACE = os.environ['EVENT_HUB_HOSTNAME'] EVENTHUB_NAME = os.environ['EVENT_HUB_NAME'] From 27d80e2494edfd9bc45bf8b35646487cd36be5af Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 22:41:52 -0700 Subject: [PATCH 23/33] update test --- .../livetest/asynctests/test_auth_async.py | 39 ++++++++----------- .../tests/livetest/synctests/test_auth.py | 21 ++++++---- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py index 56254a924f88..baa9b23f1f30 100644 --- a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py +++ b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py @@ -135,27 +135,22 @@ async def test_client_azure_sas_credential_async(self, await producer_client.send_batch(batch) @pytest.mark.liveTest - @pytest.mark.live_test_only - @CachedResourceGroupPreparer(name_prefix='eventhubtest') - @CachedEventHubNamespacePreparer(name_prefix='eventhubtest') - @CachedEventHubPreparer(name_prefix='eventhubtest') - async def test_client_azure_sas_credential_async(self, - eventhub, - eventhub_namespace, - eventhub_namespace_key_name, - eventhub_namespace_primary_key, - eventhub_namespace_connection_string, - **kwargs): + @pytest.mark.asyncio + async def test_client_azure_named_key_credential_async(live_eventhub): hostname = "{}.servicebus.windows.net".format(eventhub_namespace.name) - producer_client = EventHubProducerClient(fully_qualified_namespace=hostname, - eventhub_name=eventhub.name, - credential=AzureNamedKeyCredential( - eventhub_namespace_key_name, - eventhub_namespace_primary_key - )) - - async with producer_client: - batch = await producer_client.create_batch(partition_id='0') - batch.add(EventData(body='A single message')) - await producer_client.send_batch(batch) \ No newline at end of file + consumer_client = EventHubConsumerClient(fully_qualified_namespace=live_eventhub['hostname'], + eventhub_name=live_eventhub['event_hub'], + consumer_group='$default', + credential=credential, + 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 diff --git a/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py b/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py index dd378b196cd0..d58edbf9e091 100644 --- a/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py +++ b/sdk/eventhub/azure-eventhub/tests/livetest/synctests/test_auth.py @@ -110,14 +110,19 @@ def test_client_azure_sas_credential(live_eventhub): @pytest.mark.liveTest def test_client_azure_named_key_credential(live_eventhub): - hostname = live_eventhub['hostname'] - credential = AzureNamedKeyCredential(live_eventhub['key_name'], live_eventhub['access_key']) - producer_client = EventHubProducerClient(fully_qualified_namespace=hostname, + consumer_client = EventHubConsumerClient(fully_qualified_namespace=live_eventhub['hostname'], eventhub_name=live_eventhub['event_hub'], - credential=credential) + consumer_group='$default', + credential=credential, + user_agent='customized information') - with producer_client: - batch = producer_client.create_batch(partition_id='0') - batch.add(EventData(body='A single message')) - producer_client.send_batch(batch) \ No newline at end of file + 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 From 005af59ddb64227141c13d1e64777fa4d0b56ac2 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 22:42:36 -0700 Subject: [PATCH 24/33] analyze --- shared_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_requirements.txt b/shared_requirements.txt index b5df03e3402d..f0ae937a75d4 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -131,7 +131,7 @@ pyjwt>=1.7.1 #override azure-core-tracing-opentelemetry azure-core<2.0.0,>=1.13.0 #override azure-cosmos azure-core<2.0.0,>=1.0.0 #override azure-data-tables azure-core<2.0.0,>=1.13.0 -#override azure-eventhub azure-core<2.0.0,>=1.13.0 +#override azure-eventhub azure-core<2.0.0,>=1.14.0 #override azure-identity azure-core<2.0.0,>=1.0.0 #override azure-keyvault-administration msrest>=0.6.21 #override azure-keyvault-certificates msrest>=0.6.0 From cd0cc62e974b7ba222bea3e5ae701e33a1b40063 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 22:45:11 -0700 Subject: [PATCH 25/33] lint --- .../azure-eventhub/azure/eventhub/aio/_client_base_async.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index 9cb9e2cb5d1d..e3efb9414e79 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -94,8 +94,7 @@ def __init__(self, credential): self.credential = credential self.token_type = b"servicebus.windows.net:sastoken" - async def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument - # type: (str, Any) -> _AccessToken + async def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken: # pylint:disable=unused-argument if not scopes: raise ValueError("No token scope provided.") name, key = self.credential.named_key From 31b279d3d5186fb6a7b665eb218b4210a9dec78b Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Thu, 29 Apr 2021 23:17:26 -0700 Subject: [PATCH 26/33] lint --- sdk/eventhub/azure-eventhub/azure/eventhub/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_version.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_version.py index 2f51b9a42da7..d4039734607c 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_version.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_version.py @@ -3,4 +3,4 @@ # Licensed under the MIT License. # ------------------------------------ -VERSION = "5.4.1" +VERSION = "5.5.0" From 3c13677c19b956b7ce7655f78403cdb75a61fba8 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 30 Apr 2021 00:25:44 -0700 Subject: [PATCH 27/33] mypy --- .../azure-eventhub/azure/eventhub/aio/_client_base_async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index e3efb9414e79..3d022164f677 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -94,7 +94,7 @@ def __init__(self, credential): self.credential = credential self.token_type = b"servicebus.windows.net:sastoken" - async def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken: # pylint:disable=unused-argument + 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 From c85e5c282aef538121b121f90b1d9cbda962f622 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 30 Apr 2021 11:22:11 -0700 Subject: [PATCH 28/33] Update sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py --- .../azure-eventhub/tests/livetest/asynctests/test_auth_async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py index baa9b23f1f30..7e35a94572dd 100644 --- a/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py +++ b/sdk/eventhub/azure-eventhub/tests/livetest/asynctests/test_auth_async.py @@ -138,7 +138,7 @@ async def test_client_azure_sas_credential_async(self, @pytest.mark.asyncio async def test_client_azure_named_key_credential_async(live_eventhub): - hostname = "{}.servicebus.windows.net".format(eventhub_namespace.name) + 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', From 9455bd21c972f8c24c9f601a137adaba1ca97a7b Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Fri, 30 Apr 2021 11:24:38 -0700 Subject: [PATCH 29/33] Update sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py Co-authored-by: swathipil <76007337+swathipil@users.noreply.github.com> --- .../authenticate_with_named_key_credential_async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py index 8dbc44c374ec..29ace6f80a2a 100644 --- a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py +++ b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py @@ -6,7 +6,7 @@ # -------------------------------------------------------------------------------------------- """ -Example to demonstrate utilizing AzureNamedKeyCredential to authenticate with Event Hubs. +Example to demonstrate utilizing AzureNamedKeyCredential to authenticate with Event Hubs asynchronously. """ # pylint: disable=C0111 From dd9ea6c194db66bdc2e9baf96f85723b34168b11 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 16:29:44 -0700 Subject: [PATCH 30/33] Apply suggestions from code review Co-authored-by: Adam Ling (MSFT) --- .../azure-eventhub/azure/eventhub/_client_base.py | 9 +++++---- .../azure/eventhub/aio/_client_base_async.py | 6 +++--- .../authenticate_with_named_key_credential_async.py | 4 ++-- .../authenticate_with_named_key_credential.py | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py index 16711ccad5f3..9b92e0024297 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py @@ -177,19 +177,20 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument class AzureNamedKeyTokenCredential(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) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index 3d022164f677..aed9cdf9228f 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -89,15 +89,15 @@ class AzureNamedKeyTokenCredentialAsync(object): :param str credential: The AzureNamedKeyCredential that should be used """ - 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) diff --git a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py index 29ace6f80a2a..e07e6f48630b 100644 --- a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py +++ b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py @@ -21,8 +21,8 @@ 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'] +EVENTHUB_POLICY_NAME = os.environ['EVENT_HUB_SAS_POLICY'] +EVENTHUB_KEY = os.environ['EVENT_HUB_SAS_KEY'] credential = AzureNamedKeyCredential(EVENTHUB_POLICY_NAME, EVENTHUB_KEY) diff --git a/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py index ab654f37c229..a230971d37b5 100644 --- a/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py +++ b/sdk/eventhub/azure-eventhub/samples/sync_samples/authenticate_with_named_key_credential.py @@ -20,8 +20,8 @@ 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'] +EVENTHUB_POLICY_NAME = os.environ['EVENT_HUB_SAS_POLICY'] +EVENTHUB_KEY = os.environ['EVENT_HUB_SAS_KEY'] credential = AzureNamedKeyCredential(EVENTHUB_POLICY_NAME, EVENTHUB_KEY) From b73b4196ad34541f0d4c170df53df667131d90c4 Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 18:02:03 -0700 Subject: [PATCH 31/33] rename --- .../azure-eventhub/azure/eventhub/_client_base.py | 8 ++++---- .../azure/eventhub/aio/_client_base_async.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py index 9b92e0024297..25c3f41ced25 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/_client_base.py @@ -174,7 +174,7 @@ 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 EventhubAzureNamedKeyTokenCredential(object): """The named key credential used for authentication. :param credential: The AzureNamedKeyCredential that should be used. @@ -217,7 +217,7 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument """ return AccessToken(self.token, self.expiry) -class AzureSasTokenCredential(object): +class EventhubAzureSasTokenCredential(object): """The shared access token credential used for authentication when AzureSasCredential is provided. @@ -254,9 +254,9 @@ def __init__(self, fully_qualified_namespace, eventhub_name, credential, **kwarg self._address = _Address(hostname=fully_qualified_namespace, path=path) self._container_id = CONTAINER_PREFIX + str(uuid.uuid4())[:8] if isinstance(credential, AzureSasCredential): - self._credential = AzureSasTokenCredential(credential) + self._credential = EventhubAzureSasTokenCredential(credential) elif isinstance(credential, AzureNamedKeyCredential): - self._credential = AzureNamedKeyTokenCredential(credential) # type: ignore + self._credential = EventhubAzureNamedKeyTokenCredential(credential) # type: ignore else: self._credential = credential #type: ignore self._keep_alive = kwargs.get("keep_alive", 30) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index aed9cdf9228f..deaa1339fd43 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -83,7 +83,7 @@ async def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken: # pylint """ return AccessToken(self.token, self.expiry) -class AzureNamedKeyTokenCredentialAsync(object): +class EventhubAzureNamedKeyTokenCredentialAsync(object): """The named key credential used for authentication. :param str credential: The AzureNamedKeyCredential that should be used @@ -101,7 +101,7 @@ async def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument return _generate_sas_token(scopes[0], name, key) -class AzureSasTokenCredentialAsync(object): +class EventhubAzureSasTokenCredentialAsync(object): """The shared access token credential used for authentication when AzureSasCredential is provided. @@ -130,9 +130,9 @@ def __init__( ) -> None: self._loop = kwargs.pop("loop", None) if isinstance(credential, AzureSasCredential): - self._credential = AzureSasTokenCredentialAsync(credential) # type: ignore + self._credential = EventhubAzureSasTokenCredentialAsync(credential) # type: ignore elif isinstance(credential, AzureNamedKeyCredential): - self._credential = AzureNamedKeyTokenCredentialAsync(credential) # type: ignore + self._credential = EventhubAzureNamedKeyTokenCredentialAsync(credential) # type: ignore else: self._credential = credential # type: ignore super(ClientBaseAsync, self).__init__( From 77e90d9f756f1d383eb4928c296a2e694e61ff9f Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 18:07:57 -0700 Subject: [PATCH 32/33] Update sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py Co-authored-by: Adam Ling (MSFT) --- .../azure-eventhub/azure/eventhub/aio/_client_base_async.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py index deaa1339fd43..548ddab1a9e0 100644 --- a/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py +++ b/sdk/eventhub/azure-eventhub/azure/eventhub/aio/_client_base_async.py @@ -86,7 +86,8 @@ async def get_token(self, *scopes: str, **kwargs: Any) -> AccessToken: # pylint class EventhubAzureNamedKeyTokenCredentialAsync(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, azure_named_key_credential): From ee9548d86d1cc576f31bf947b6f60e17e19a805f Mon Sep 17 00:00:00 2001 From: Rakshith Bhyravabhotla Date: Mon, 3 May 2021 19:17:56 -0700 Subject: [PATCH 33/33] ops --- .../authenticate_with_named_key_credential_async.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py index e07e6f48630b..7db60b184348 100644 --- a/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py +++ b/sdk/eventhub/azure-eventhub/samples/async_samples/authenticate_with_named_key_credential_async.py @@ -12,6 +12,7 @@ # pylint: disable=C0111 import os +import asyncio import time from azure.core.credentials import AzureNamedKeyCredential from azure.eventhub.aio import EventHubProducerClient