Skip to content

Commit fe1bae6

Browse files
committed
Revert "reverted addition of core changes to this pr"
This reverts commit 7b3f2ad.
1 parent 7b3f2ad commit fe1bae6

File tree

5 files changed

+108
-4
lines changed

5 files changed

+108
-4
lines changed

sdk/core/azure-core/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
### Features
77

88
- Support a default error type in map_error #9773
9+
- Added `AzureKeyCredential` and its respective policy.
910

1011
## 1.3.0 (2020-03-09)
1112

sdk/core/azure-core/azure/core/credentials.py

+43
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# license information.
55
# -------------------------------------------------------------------------
66
from typing import TYPE_CHECKING
7+
import six
78

89

910
if TYPE_CHECKING:
@@ -28,3 +29,45 @@ def get_token(self, *scopes, **kwargs):
2829
from collections import namedtuple
2930

3031
AccessToken = namedtuple("AccessToken", ["token", "expires_on"])
32+
33+
__all__ = ["AzureKeyCredential"]
34+
35+
36+
class AzureKeyCredential(object):
37+
"""Credential type used for authenticating to an Azure service.
38+
It provides the ability to update the key without creating a new client.
39+
40+
:param str key: The key used to authenticate to an Azure service
41+
:raises: TypeError
42+
"""
43+
44+
def __init__(self, key):
45+
# type: (str) -> None
46+
if not isinstance(key, six.string_types):
47+
raise TypeError("key must be a string.")
48+
self._key = key # type: str
49+
50+
@property
51+
def key(self):
52+
# type () -> str
53+
"""The value of the configured key.
54+
55+
:rtype: str
56+
"""
57+
return self._key
58+
59+
def update(self, key):
60+
# type: (str) -> None
61+
"""Update the key.
62+
63+
This can be used when you've regenerated your service key and want
64+
to update long-lived clients.
65+
66+
:param str key: The key used to authenticate to an Azure service
67+
:raises: ValueError or TypeError
68+
"""
69+
if not key:
70+
raise ValueError("The key used for updating can not be None or empty")
71+
if not isinstance(key, six.string_types):
72+
raise TypeError("The key used for updating must be a string.")
73+
self._key = key

sdk/core/azure-core/azure/core/pipeline/policies/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
# --------------------------------------------------------------------------
2626

2727
from ._base import HTTPPolicy, SansIOHTTPPolicy, RequestHistory
28-
from ._authentication import BearerTokenCredentialPolicy
28+
from ._authentication import BearerTokenCredentialPolicy, AzureKeyCredentialPolicy
2929
from ._custom_hook import CustomHookPolicy
3030
from ._redirect import RedirectPolicy
3131
from ._retry import RetryPolicy, RetryMode
@@ -44,6 +44,7 @@
4444
'HTTPPolicy',
4545
'SansIOHTTPPolicy',
4646
'BearerTokenCredentialPolicy',
47+
'AzureKeyCredentialPolicy',
4748
'HeadersPolicy',
4849
'UserAgentPolicy',
4950
'NetworkTraceLoggingPolicy',

sdk/core/azure-core/azure/core/pipeline/policies/_authentication.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# license information.
55
# -------------------------------------------------------------------------
66
import time
7+
import six
78

89
from . import SansIOHTTPPolicy
910
from ...exceptions import ServiceRequestError
@@ -16,7 +17,7 @@
1617
if TYPE_CHECKING:
1718
# pylint:disable=unused-import
1819
from typing import Any, Dict, Mapping, Optional
19-
from azure.core.credentials import AccessToken, TokenCredential
20+
from azure.core.credentials import AccessToken, TokenCredential, AzureKeyCredential
2021
from azure.core.pipeline import PipelineRequest
2122

2223

@@ -91,3 +92,25 @@ def on_request(self, request):
9192
if self._need_new_token:
9293
self._token = self._credential.get_token(*self._scopes)
9394
self._update_headers(request.http_request.headers, self._token.token) # type: ignore
95+
96+
97+
class AzureKeyCredentialPolicy(SansIOHTTPPolicy):
98+
"""Adds a key header for the provided credential.
99+
100+
:param credential: The credential used to authenticate requests.
101+
:type credential: ~azure.core.credentials.AzureKeyCredential
102+
:param str name: The name of the key header used for the credential.
103+
:raises: ValueError or TypeError
104+
"""
105+
def __init__(self, credential, name):
106+
# type: (AzureKeyCredential, str) -> None
107+
super(AzureKeyCredentialPolicy, self).__init__()
108+
self._credential = credential
109+
if not name:
110+
raise ValueError("name can not be None or empty")
111+
if not isinstance(name, six.string_types):
112+
raise TypeError("name must be a string.")
113+
self._name = name
114+
115+
def on_request(self, request):
116+
request.http_request.headers[self._name] = self._credential.key

sdk/core/azure-core/tests/test_authentication.py

+38-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
import time
77

88
import azure.core
9-
from azure.core.credentials import AccessToken
9+
from azure.core.credentials import AccessToken, AzureKeyCredential
1010
from azure.core.exceptions import ServiceRequestError
1111
from azure.core.pipeline import Pipeline
12-
from azure.core.pipeline.policies import BearerTokenCredentialPolicy, SansIOHTTPPolicy
12+
from azure.core.pipeline.policies import BearerTokenCredentialPolicy, SansIOHTTPPolicy, AzureKeyCredentialPolicy
1313
from azure.core.pipeline.transport import HttpRequest
1414

1515
import pytest
@@ -146,3 +146,39 @@ def test_key_vault_regression():
146146
policy._token = AccessToken(token, time.time() + 3600)
147147
assert not policy._need_new_token
148148
assert policy._token.token == token
149+
150+
def test_azure_key_credential_policy():
151+
"""Tests to see if we can create an AzureKeyCredentialPolicy"""
152+
def verify_authorization_header(request):
153+
assert request.http_request.headers["api_key"] == "test_key"
154+
api_key = "test_key"
155+
key_header = "api_key"
156+
157+
transport=Mock(send=verify_authorization_header)
158+
credential = AzureKeyCredential(api_key)
159+
credential_policy = AzureKeyCredentialPolicy(credential=credential, name=key_header)
160+
pipeline = Pipeline(transport=Mock(), policies=[credential_policy])
161+
162+
pipeline.run(HttpRequest("GET", "https://test_key_credential"))
163+
164+
def test_azure_key_credential_policy_raises():
165+
"""Tests AzureKeyCredential and AzureKeyCredentialPolicy raises with non-string input parameters."""
166+
api_key = 1234
167+
key_header = 5678
168+
with pytest.raises(TypeError):
169+
credential = AzureKeyCredential(api_key)
170+
171+
credential = AzureKeyCredential(str(api_key))
172+
with pytest.raises(TypeError):
173+
credential_policy = AzureKeyCredentialPolicy(credential=credential, name=key_header)
174+
175+
def test_azure_key_credential_updates():
176+
"""Tests AzureKeyCredential updates"""
177+
api_key = "original"
178+
179+
credential = AzureKeyCredential(api_key)
180+
assert credential.key == "original"
181+
182+
api_key = "new"
183+
credential.update(api_key)
184+
assert credential.key == "new"

0 commit comments

Comments
 (0)