Skip to content

Commit

Permalink
Add prefix to AzureKeyCredential policy (Azure#29901)
Browse files Browse the repository at this point in the history
* Add Http spec auth policy

* More types

* Fix typing

* Typing fix

* Fix import

* Add prefix to policy

* Typing

* Pylint

* Rename to scheme

* ChangLoge

* Rename to prefix

* Update CHANGELOG.md
  • Loading branch information
lmazuel authored May 22, 2023
1 parent d99416c commit 862ff38
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 5 deletions.
1 change: 1 addition & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Features Added

- Added support to use sync credentials in `AsyncBearerTokenCredentialPolicy`. #30381
- Added "prefix" parameter to AzureKeyCredentialPolicy #29901

### Breaking Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# license information.
# -------------------------------------------------------------------------
import time
from typing import TYPE_CHECKING, Dict, Optional
from typing import TYPE_CHECKING, Dict, Optional, TypeVar

from . import HTTPPolicy, SansIOHTTPPolicy
from ...exceptions import ServiceRequestError
Expand All @@ -18,6 +18,9 @@
AzureSasCredential,
)
from azure.core.pipeline import PipelineRequest, PipelineResponse
from azure.core.pipeline.policies._universal import HTTPRequestType

HTTPResponseTypeVar = TypeVar("HTTPResponseTypeVar")


# pylint:disable=too-few-public-methods
Expand Down Expand Up @@ -160,17 +163,23 @@ def on_exception(self, request: "PipelineRequest") -> None:
return


class AzureKeyCredentialPolicy(SansIOHTTPPolicy):
class AzureKeyCredentialPolicy(SansIOHTTPPolicy["HTTPRequestType", HTTPResponseTypeVar]):
"""Adds a key header for the provided credential.
:param credential: The credential used to authenticate requests.
:type credential: ~azure.core.credentials.AzureKeyCredential
:param str name: The name of the key header used for the credential.
:keyword str prefix: The name of the prefix for the header value if any.
:raises: ValueError or TypeError
"""

def __init__(
self, credential: "AzureKeyCredential", name: str, **kwargs # pylint: disable=unused-argument
self,
credential: "AzureKeyCredential",
name: str,
*,
prefix: Optional[str] = None,
**kwargs, # pylint: disable=unused-argument
) -> None:
super(AzureKeyCredentialPolicy, self).__init__()
self._credential = credential
Expand All @@ -179,9 +188,10 @@ def __init__(
if not isinstance(name, str):
raise TypeError("name must be a string.")
self._name = name
self._prefix = prefix + " " if prefix else ""

def on_request(self, request):
request.http_request.headers[self._name] = self._credential.key
def on_request(self, request: "PipelineRequest[HTTPRequestType]") -> None:
request.http_request.headers[self._name] = f"{self._prefix}{self._credential.key}"


class AzureSasCredentialPolicy(SansIOHTTPPolicy):
Expand Down
19 changes: 19 additions & 0 deletions sdk/core/azure-core/tests/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,3 +409,22 @@ def test_azure_named_key_credential_raises():

with pytest.raises(TypeError, match="Both name and key must be strings."):
cred.update(1234, "newkey")


@pytest.mark.parametrize("http_request", HTTP_REQUESTS)
def test_azure_http_credential_policy(http_request):
"""Tests to see if we can create an AzureHttpKeyCredentialPolicy"""

prefix = "SharedAccessKey"
api_key = "test_key"
header_content = f"{prefix} {api_key}"

def verify_authorization_header(request):
assert request.headers["Authorization"] == header_content

transport = Mock(send=verify_authorization_header)
credential = AzureKeyCredential(api_key)
credential_policy = AzureKeyCredentialPolicy(credential=credential, name="Authorization", prefix=prefix)
pipeline = Pipeline(transport=transport, policies=[credential_policy])

pipeline.run(http_request("GET", "https://test_key_credential"))

0 comments on commit 862ff38

Please sign in to comment.