diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/__init__.py index ab1a4e0c3f8e..c00fd1461b4b 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/__init__.py @@ -3,6 +3,5 @@ # Licensed under the MIT License. # ------------------------------------- from ._client import KeyClient -from ._models import Key, KeyBase, DeletedKey, KeyOperationResult __all__ = ["KeyClient"] diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py index 996683569bb9..90aeb33200d9 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py @@ -2,16 +2,23 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from typing import Any, Dict, Generator, Mapping, Optional, List from datetime import datetime +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + from typing import Any, Dict, Generator, Mapping, Optional + from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError -from ._internal import _KeyVaultClientBase +from ._shared import KeyVaultClientBase from ._models import Key, KeyBase, DeletedKey, KeyOperationResult -class KeyClient(_KeyVaultClientBase): +class KeyClient(KeyVaultClientBase): """KeyClient is a high-level interface for managing a vault's keys. Example: diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py index e8609bdd32a7..19ceda29966a 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py @@ -2,12 +2,19 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------- - import datetime -from typing import Any, Dict, Mapping, Optional + +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + from typing import Any, Dict, Generator, Mapping, Optional + from collections import namedtuple -from ._internal import _parse_vault_id -from ._generated.v7_0 import models +from ._shared import parse_vault_id +from ._shared._generated.v7_0 import models KeyOperationResult = namedtuple("KeyOperationResult", ["id", "value"]) @@ -19,7 +26,7 @@ def __init__(self, attributes, vault_id, **kwargs): # type: (models.KeyAttributes, str, Mapping[str, Any]) -> None self._attributes = attributes self._id = vault_id - self._vault_id = _parse_vault_id(vault_id) + self._vault_id = parse_vault_id(vault_id) self._managed = kwargs.get("managed", None) self._tags = kwargs.get("tags", None) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/__init__.py index ab72f9b729cf..beb24c202495 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/__init__.py @@ -2,15 +2,55 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from collections import namedtuple + +try: + import urllib.parse as parse +except ImportError: + # pylint:disable=import-error + import urlparse as parse # type: ignore + from .challenge_auth_policy import ChallengeAuthPolicy, ChallengeAuthPolicyBase +from .client_base import KeyVaultClientBase from .http_challenge import HttpChallenge from . import http_challenge_cache as HttpChallengeCache -__all__ = ["ChallengeAuthPolicy", "ChallengeAuthPolicyBase", "HttpChallenge", "HttpChallengeCache"] +__all__ = [ + "ChallengeAuthPolicy", + "ChallengeAuthPolicyBase", + "HttpChallenge", + "HttpChallengeCache", + "KeyVaultClientBase", +] + +_VaultId = namedtuple("VaultId", ["vault_url", "collection", "name", "version"]) + + +def parse_vault_id(url): + try: + parsed_uri = parse.urlparse(url) + except Exception: # pylint: disable=broad-except + raise ValueError("'{}' is not not a valid url".format(url)) + if not (parsed_uri.scheme and parsed_uri.hostname): + raise ValueError("'{}' is not not a valid url".format(url)) + + path = list(filter(None, parsed_uri.path.split("/"))) + + if len(path) < 2 or len(path) > 3: + raise ValueError("'{}' is not not a valid vault url".format(url)) + + return _VaultId( + vault_url="{}://{}".format(parsed_uri.scheme, parsed_uri.hostname), + collection=path[0], + name=path[1], + version=path[2] if len(path) == 3 else None, + ) + try: from .async_challenge_auth_policy import AsyncChallengeAuthPolicy + from .async_client_base import AsyncKeyVaultClientBase, AsyncPagingAdapter - __all__.append("AsyncChallengeAuthPolicy") + __all__.extend(["AsyncChallengeAuthPolicy", "AsyncKeyVaultClientBase", "AsyncPagingAdapter"]) except (SyntaxError, ImportError): pass diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/key_vault_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/key_vault_client.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/_configuration.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/_configuration.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/_configuration.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/_configuration.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/_key_vault_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/_key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/_key_vault_client.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/_key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/_configuration_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/_configuration_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/_configuration_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/_configuration_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/_key_vault_client_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/_key_vault_client_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/_key_vault_client_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/_key_vault_client_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/operations_async/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/operations_async/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/operations_async/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/operations_async/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_key_vault_client_enums.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_key_vault_client_enums.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_key_vault_client_enums.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_key_vault_client_enums.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_models.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_models.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_models_py3.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_models_py3.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_models_py3.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_models_py3.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_paged_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_paged_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/models/_paged_models.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/models/_paged_models.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/operations/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/operations/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/operations/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/operations/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/operations/_key_vault_client_operations.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/operations/_key_vault_client_operations.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/operations/_key_vault_client_operations.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/operations/_key_vault_client_operations.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/version.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/version.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v2016_10_01/version.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v2016_10_01/version.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/_configuration.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/_configuration.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/_configuration.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/_configuration.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/_key_vault_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/_key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/_key_vault_client.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/_key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/_configuration_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/_configuration_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/_configuration_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/_configuration_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/_key_vault_client_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/_key_vault_client_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/_key_vault_client_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/_key_vault_client_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/operations_async/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/operations_async/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/operations_async/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/operations_async/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_key_vault_client_enums.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_key_vault_client_enums.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_key_vault_client_enums.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_key_vault_client_enums.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_models.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_models.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_models_py3.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_models_py3.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_models_py3.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_models_py3.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_paged_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_paged_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/models/_paged_models.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/models/_paged_models.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/operations/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/operations/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/operations/__init__.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/operations/__init__.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/operations/_key_vault_client_operations.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/operations/_key_vault_client_operations.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/operations/_key_vault_client_operations.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/operations/_key_vault_client_operations.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/version.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/version.py similarity index 100% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_generated/v7_0/version.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/_generated/v7_0/version.py diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_internal.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/async_client_base.py similarity index 96% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_internal.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/async_client_base.py index 45d7962ccbaa..7424b5162ea3 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_internal.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/async_client_base.py @@ -9,8 +9,8 @@ from azure.core.pipeline.transport import AsyncioRequestsTransport, HttpTransport from msrest.serialization import Model -from azure.keyvault.keys._generated import KeyVaultClient -from azure.keyvault.keys._shared import AsyncChallengeAuthPolicy +from ._generated import KeyVaultClient +from . import AsyncChallengeAuthPolicy if TYPE_CHECKING: @@ -40,7 +40,7 @@ async def __anext__(self) -> Any: # TODO: expected type Model got Coroutine instead? -class _AsyncKeyVaultClientBase: +class AsyncKeyVaultClientBase: """ :param credential: A credential or credential provider which can be used to authenticate to the vault, a ValueError will be raised if the entity is not provided diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_internal.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/client_base.py similarity index 76% rename from sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_internal.py rename to sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/client_base.py index 7bd6a386ad4a..147dc0506b76 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_internal.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_shared/client_base.py @@ -2,7 +2,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from collections import namedtuple from typing import TYPE_CHECKING from azure.core import Configuration from azure.core.pipeline import Pipeline @@ -15,41 +14,13 @@ from azure.core.credentials import TokenCredential from azure.core.pipeline.transport import HttpTransport -try: - import urllib.parse as parse -except ImportError: - import urlparse as parse # pylint: disable=import-error - -from ._shared.challenge_auth_policy import ChallengeAuthPolicy - -_VaultId = namedtuple("VaultId", ["vault_url", "collection", "name", "version"]) +from .challenge_auth_policy import ChallengeAuthPolicy KEY_VAULT_SCOPE = "https://vault.azure.net/.default" -def _parse_vault_id(url): - try: - parsed_uri = parse.urlparse(url) - except Exception: # pylint: disable=broad-except - raise ValueError("'{}' is not not a valid url".format(url)) - if not (parsed_uri.scheme and parsed_uri.hostname): - raise ValueError("'{}' is not not a valid url".format(url)) - - path = list(filter(None, parsed_uri.path.split("/"))) - - if len(path) < 2 or len(path) > 3: - raise ValueError("'{}' is not not a valid vault url".format(url)) - - return _VaultId( - vault_url="{}://{}".format(parsed_uri.scheme, parsed_uri.hostname), - collection=path[0], - name=path[1], - version=path[2] if len(path) == 3 else None, - ) - - -class _KeyVaultClientBase(object): +class KeyVaultClientBase(object): """ :param credential: A credential or credential provider which can be used to authenticate to the vault, a ValueError will be raised if the entity is not provided diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/__init__.py index 718493f543ea..71cad7e66b18 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/__init__.py @@ -3,6 +3,5 @@ # Licensed under the MIT License. # ------------------------------------ from ._client import KeyClient -from .._models import Key, KeyBase, DeletedKey, KeyOperationResult __all__ = ["KeyClient"] diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py index 3e686b185d62..9f81bbdc5a7b 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py @@ -8,10 +8,10 @@ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError from azure.keyvault.keys._models import Key, DeletedKey, KeyBase, KeyOperationResult -from ._internal import _AsyncKeyVaultClientBase, AsyncPagingAdapter +from azure.keyvault.keys._shared import AsyncKeyVaultClientBase, AsyncPagingAdapter -class KeyClient(_AsyncKeyVaultClientBase): +class KeyClient(AsyncKeyVaultClientBase): """The KeyClient class defines a high level interface for managing keys in the specified vault. Example: diff --git a/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client.py b/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client.py index cec73c1d9d8f..8cce3b685889 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client.py @@ -7,7 +7,7 @@ except ImportError: TYPE_CHECKING = False -from azure.keyvault.keys._internal import _KeyVaultClientBase +from azure.keyvault.keys._shared import KeyVaultClientBase from azure.keyvault.keys import KeyClient if TYPE_CHECKING: @@ -18,7 +18,7 @@ from typing import Any, Optional -class VaultClient(_KeyVaultClientBase): +class VaultClient(KeyVaultClientBase): def __init__(self, vault_url, credential, config=None, transport=None, api_version=None, **kwargs): # type: (str, TokenCredential, Configuration, Optional[HttpTransport], Optional[str], **Any) -> None super(VaultClient, self).__init__( diff --git a/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client_async.py index 4d4614d46fe1..f99e9609e3a3 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/keys_vault_client_async.py @@ -10,9 +10,8 @@ from azure.core.pipeline.transport import AsyncioRequestsTransport, HttpTransport from msrest.serialization import Model -from azure.keyvault.keys._generated import KeyVaultClient from azure.keyvault.keys.aio import KeyClient -from azure.keyvault.keys.aio._internal import _AsyncKeyVaultClientBase +from azure.keyvault.keys._shared import AsyncKeyVaultClientBase if TYPE_CHECKING: try: @@ -24,7 +23,7 @@ KEY_VAULT_SCOPE = "https://vault.azure.net/.default" -class VaultClient(_AsyncKeyVaultClientBase): +class VaultClient(AsyncKeyVaultClientBase): def __init__( self, vault_url: str, diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py index b2b29fb1b737..0f736d0e5bcd 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py @@ -8,7 +8,7 @@ import time from azure.core.exceptions import ResourceNotFoundError -from azure.keyvault.keys._generated.v7_0.models import JsonWebKey +from azure.keyvault.keys._shared._generated.v7_0.models import JsonWebKey from keys_preparer import VaultClientPreparer from keys_test_case import KeyVaultTestCase from devtools_testutils import ResourceGroupPreparer diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py index dc7e701f1e13..0d3d4894c487 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py @@ -11,7 +11,7 @@ from keys_async_preparer import AsyncVaultClientPreparer from keys_async_test_case import AsyncKeyVaultTestCase -from azure.keyvault.keys._generated.v7_0.models import JsonWebKey +from azure.keyvault.keys._shared._generated.v7_0.models import JsonWebKey from dateutil import parser as date_parse diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/__init__.py index 34de167e8c94..44967833f2df 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/__init__.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/__init__.py @@ -3,6 +3,5 @@ # Licensed under the MIT License. # ------------------------------------ from ._client import SecretClient -from ._models import Secret, SecretAttributes, DeletedSecret __all__ = ["SecretClient"] diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_client.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_client.py index b31ff0047445..f15b6779b9d3 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_client.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_client.py @@ -2,16 +2,23 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from typing import Any, Dict, Generator, Mapping, Optional from datetime import datetime +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + from typing import Any, Dict, Generator, Mapping, Optional + from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError -from ._internal import _KeyVaultClientBase +from ._shared import KeyVaultClientBase from ._models import Secret, DeletedSecret, SecretAttributes -class SecretClient(_KeyVaultClientBase): +class SecretClient(KeyVaultClientBase): """SecretClient is a high-level interface for managing a vault's secrets. Example: diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_models.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_models.py index 9436afc6c8fa..a8629aeeee28 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_models.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_models.py @@ -2,11 +2,18 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ - import datetime -from typing import Any, Dict, Mapping, Optional -from ._generated.v7_0 import models -from ._internal import _parse_vault_id + +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + from typing import Any, Dict, Mapping, Optional + +from ._shared import parse_vault_id +from ._shared._generated.v7_0 import models class SecretAttributes(object): @@ -16,7 +23,7 @@ def __init__(self, attributes, vault_id, **kwargs): # type: (models.SecretAttributes, str, Mapping[str, Any]) -> None self._attributes = attributes self._id = vault_id - self._vault_id = _parse_vault_id(vault_id) + self._vault_id = parse_vault_id(vault_id) self._content_type = kwargs.get("content_type", None) self._key_id = kwargs.get("key_id", None) self._managed = kwargs.get("managed", None) diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/__init__.py new file mode 100644 index 000000000000..beb24c202495 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/__init__.py @@ -0,0 +1,56 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from collections import namedtuple + +try: + import urllib.parse as parse +except ImportError: + # pylint:disable=import-error + import urlparse as parse # type: ignore + +from .challenge_auth_policy import ChallengeAuthPolicy, ChallengeAuthPolicyBase +from .client_base import KeyVaultClientBase +from .http_challenge import HttpChallenge +from . import http_challenge_cache as HttpChallengeCache + +__all__ = [ + "ChallengeAuthPolicy", + "ChallengeAuthPolicyBase", + "HttpChallenge", + "HttpChallengeCache", + "KeyVaultClientBase", +] + +_VaultId = namedtuple("VaultId", ["vault_url", "collection", "name", "version"]) + + +def parse_vault_id(url): + try: + parsed_uri = parse.urlparse(url) + except Exception: # pylint: disable=broad-except + raise ValueError("'{}' is not not a valid url".format(url)) + if not (parsed_uri.scheme and parsed_uri.hostname): + raise ValueError("'{}' is not not a valid url".format(url)) + + path = list(filter(None, parsed_uri.path.split("/"))) + + if len(path) < 2 or len(path) > 3: + raise ValueError("'{}' is not not a valid vault url".format(url)) + + return _VaultId( + vault_url="{}://{}".format(parsed_uri.scheme, parsed_uri.hostname), + collection=path[0], + name=path[1], + version=path[2] if len(path) == 3 else None, + ) + + +try: + from .async_challenge_auth_policy import AsyncChallengeAuthPolicy + from .async_client_base import AsyncKeyVaultClientBase, AsyncPagingAdapter + + __all__.extend(["AsyncChallengeAuthPolicy", "AsyncKeyVaultClientBase", "AsyncPagingAdapter"]) +except (SyntaxError, ImportError): + pass diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/key_vault_client.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/key_vault_client.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/_configuration.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/_configuration.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/_configuration.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/_configuration.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/_key_vault_client.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/_key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/_key_vault_client.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/_key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/_configuration_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/_configuration_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/_configuration_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/_configuration_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/_key_vault_client_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/_key_vault_client_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/_key_vault_client_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/_key_vault_client_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/operations_async/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/operations_async/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/operations_async/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/operations_async/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/aio/operations_async/_key_vault_client_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_key_vault_client_enums.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_key_vault_client_enums.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_key_vault_client_enums.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_key_vault_client_enums.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_models.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_models.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_models.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_models_py3.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_models_py3.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_models_py3.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_models_py3.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_paged_models.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_paged_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/models/_paged_models.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/models/_paged_models.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/operations/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/operations/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/operations/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/operations/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/operations/_key_vault_client_operations.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/operations/_key_vault_client_operations.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/operations/_key_vault_client_operations.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/operations/_key_vault_client_operations.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/version.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/version.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v2016_10_01/version.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v2016_10_01/version.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/_configuration.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/_configuration.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/_configuration.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/_configuration.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/_key_vault_client.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/_key_vault_client.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/_key_vault_client.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/_key_vault_client.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/_configuration_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/_configuration_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/_configuration_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/_configuration_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/_key_vault_client_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/_key_vault_client_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/_key_vault_client_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/_key_vault_client_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/operations_async/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/operations_async/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/operations_async/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/operations_async/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/aio/operations_async/_key_vault_client_operations_async.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_key_vault_client_enums.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_key_vault_client_enums.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_key_vault_client_enums.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_key_vault_client_enums.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_models.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_models.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_models.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_models_py3.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_models_py3.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_models_py3.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_models_py3.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_paged_models.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_paged_models.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/models/_paged_models.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/models/_paged_models.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/operations/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/operations/__init__.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/operations/__init__.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/operations/__init__.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/operations/_key_vault_client_operations.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/operations/_key_vault_client_operations.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/operations/_key_vault_client_operations.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/operations/_key_vault_client_operations.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/version.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/version.py similarity index 100% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_generated/v7_0/version.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/_generated/v7_0/version.py diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_challenge_auth_policy.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_challenge_auth_policy.py new file mode 100644 index 000000000000..d07718d9c5e6 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_challenge_auth_policy.py @@ -0,0 +1,57 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from azure.core.pipeline import PipelineRequest +from azure.core.pipeline.policies import AsyncHTTPPolicy +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from . import ChallengeAuthPolicyBase, HttpChallenge, HttpChallengeCache + + +class AsyncChallengeAuthPolicy(ChallengeAuthPolicyBase, AsyncHTTPPolicy): + """policy for handling HTTP authentication challenges""" + + async def send(self, request: PipelineRequest) -> HttpResponse: + challenge = HttpChallengeCache.get_challenge_for_url(request.http_request.url) + if not challenge: + # provoke a challenge with an unauthorized, bodiless request + no_body = HttpRequest( + request.http_request.method, request.http_request.url, headers=request.http_request.headers + ) + if request.http_request.body: + # no_body was created with request's headers -> if request has a body, no_body's content-length is wrong + no_body.headers["Content-Length"] = "0" + + challenger = await self.next.send(PipelineRequest(http_request=no_body, context=request.context)) + try: + challenge = self._update_challenge(request, challenger) + except ValueError: + # didn't receive the expected challenge -> nothing more this policy can do + return challenger + + await self._handle_challenge(request, challenge) + response = await self.next.send(request) + + if response.http_response.status_code == 401: + # cached challenge could be outdated; maybe this response has a new one? + try: + challenge = self._update_challenge(request, response) + except ValueError: + # 401 with no legible challenge -> nothing more this policy can do + return response + + await self._handle_challenge(request, challenge) + response = await self.next.send(request) + + return response + + async def _handle_challenge(self, request: PipelineRequest, challenge: HttpChallenge) -> None: + """authenticate according to challenge, add Authorization header to request""" + + scope = challenge.get_resource() + if not scope.endswith("/.default"): + scope += "/.default" + + access_token = await self._credential.get_token(scope) + self._update_headers(request.http_request.headers, access_token.token) diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_internal.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_client_base.py similarity index 93% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_internal.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_client_base.py index d1f74f7e449e..7424b5162ea3 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_internal.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/async_client_base.py @@ -6,12 +6,11 @@ from azure.core.async_paging import AsyncPagedMixin from azure.core.configuration import Configuration from azure.core.pipeline import AsyncPipeline -from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy from azure.core.pipeline.transport import AsyncioRequestsTransport, HttpTransport from msrest.serialization import Model -from .._generated import KeyVaultClient -from .._internal import KEY_VAULT_SCOPE +from ._generated import KeyVaultClient +from . import AsyncChallengeAuthPolicy if TYPE_CHECKING: @@ -41,7 +40,7 @@ async def __anext__(self) -> Any: # TODO: expected type Model got Coroutine instead? -class _AsyncKeyVaultClientBase: +class AsyncKeyVaultClientBase: """ :param credential: A credential or credential provider which can be used to authenticate to the vault, a ValueError will be raised if the entity is not provided @@ -58,7 +57,7 @@ def create_config( if api_version is None: api_version = KeyVaultClient.DEFAULT_API_VERSION config = KeyVaultClient.get_configuration_class(api_version, aio=True)(credential, **kwargs) - config.authentication_policy = AsyncBearerTokenCredentialPolicy(credential, KEY_VAULT_SCOPE) + config.authentication_policy = AsyncChallengeAuthPolicy(credential) return config def __init__( diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/challenge_auth_policy.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/challenge_auth_policy.py new file mode 100644 index 000000000000..204a59ddc05e --- /dev/null +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/challenge_auth_policy.py @@ -0,0 +1,91 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + # pylint:disable=unused-import + from azure.core.pipeline.transport import HttpResponse + +from azure.core.pipeline import PipelineRequest +from azure.core.pipeline.policies import HTTPPolicy +from azure.core.pipeline.policies.authentication import _BearerTokenCredentialPolicyBase +from azure.core.pipeline.transport import HttpRequest + +from .http_challenge import HttpChallenge +from . import http_challenge_cache as ChallengeCache + + +class ChallengeAuthPolicyBase(_BearerTokenCredentialPolicyBase): + """Sans I/O base for challenge authentication policies""" + + def __init__(self, credential, **kwargs): + super(ChallengeAuthPolicyBase, self).__init__(credential, **kwargs) + + @staticmethod + def _update_challenge(request, challenger): + # type: (HttpRequest, HttpResponse) -> HttpChallenge + """parse challenge from challenger, cache it, return it""" + + challenge = HttpChallenge( + request.http_request.url, + challenger.http_response.headers.get("WWW-Authenticate"), + response_headers=challenger.http_response.headers, + ) + ChallengeCache.set_challenge_for_url(request.http_request.url, challenge) + return challenge + + +class ChallengeAuthPolicy(ChallengeAuthPolicyBase, HTTPPolicy): + """policy for handling HTTP authentication challenges""" + + def send(self, request): + # type: (PipelineRequest) -> HttpResponse + + challenge = ChallengeCache.get_challenge_for_url(request.http_request.url) + if not challenge: + # provoke a challenge with an unauthorized, bodiless request + no_body = HttpRequest( + request.http_request.method, request.http_request.url, headers=request.http_request.headers + ) + if request.http_request.body: + # no_body was created with request's headers -> if request has a body, no_body's content-length is wrong + no_body.headers["Content-Length"] = "0" + + challenger = self.next.send(PipelineRequest(http_request=no_body, context=request.context)) + try: + challenge = self._update_challenge(request, challenger) + except ValueError: + # didn't receive the expected challenge -> nothing more this policy can do + return challenger + + self._handle_challenge(request, challenge) + response = self.next.send(request) + + if response.http_response.status_code == 401: + # cached challenge could be outdated; maybe this response has a new one? + try: + challenge = self._update_challenge(request, response) + except ValueError: + # 401 with no legible challenge -> nothing more this policy can do + return response + + self._handle_challenge(request, challenge) + response = self.next.send(request) + + return response + + def _handle_challenge(self, request, challenge): + # type: (PipelineRequest, HttpChallenge) -> None + """authenticate according to challenge, add Authorization header to request""" + + scope = challenge.get_resource() + if not scope.endswith("/.default"): + scope += "/.default" + + access_token = self._credential.get_token(scope) + self._update_headers(request.http_request.headers, access_token.token) diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_internal.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/client_base.py similarity index 74% rename from sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_internal.py rename to sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/client_base.py index 67a6a9d71a16..147dc0506b76 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_internal.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/client_base.py @@ -2,11 +2,9 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from collections import namedtuple from typing import TYPE_CHECKING from azure.core import Configuration from azure.core.pipeline import Pipeline -from azure.core.pipeline.policies import BearerTokenCredentialPolicy from azure.core.pipeline.transport import RequestsTransport from ._generated import KeyVaultClient @@ -16,40 +14,13 @@ from azure.core.credentials import TokenCredential from azure.core.pipeline.transport import HttpTransport -try: - import urllib.parse as parse -except ImportError: - import urlparse as parse # pylint: disable=import-error - - -_VaultId = namedtuple("VaultId", ["vault_url", "collection", "name", "version"]) +from .challenge_auth_policy import ChallengeAuthPolicy KEY_VAULT_SCOPE = "https://vault.azure.net/.default" -def _parse_vault_id(url): - try: - parsed_uri = parse.urlparse(url) - except Exception: # pylint: disable=broad-except - raise ValueError("'{}' is not not a valid url".format(url)) - if not (parsed_uri.scheme and parsed_uri.hostname): - raise ValueError("'{}' is not not a valid url".format(url)) - - path = list(filter(None, parsed_uri.path.split("/"))) - - if len(path) < 2 or len(path) > 3: - raise ValueError("'{}' is not not a valid vault url".format(url)) - - return _VaultId( - vault_url="{}://{}".format(parsed_uri.scheme, parsed_uri.hostname), - collection=path[0], - name=path[1], - version=path[2] if len(path) == 3 else None, - ) - - -class _KeyVaultClientBase(object): +class KeyVaultClientBase(object): """ :param credential: A credential or credential provider which can be used to authenticate to the vault, a ValueError will be raised if the entity is not provided @@ -65,7 +36,7 @@ def create_config(credential, api_version=None, **kwargs): if api_version is None: api_version = KeyVaultClient.DEFAULT_API_VERSION config = KeyVaultClient.get_configuration_class(api_version, aio=False)(credential, **kwargs) - config.authentication_policy = BearerTokenCredentialPolicy(credential, KEY_VAULT_SCOPE) + config.authentication_policy = ChallengeAuthPolicy(credential) return config def __init__(self, vault_url, credential, config=None, transport=None, api_version=None, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge.py new file mode 100644 index 000000000000..b2e67c71a3ae --- /dev/null +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge.py @@ -0,0 +1,113 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +try: + import urllib.parse as parse +except ImportError: + import urlparse as parse # type: ignore + + +class HttpChallenge(object): + def __init__(self, request_uri, challenge, response_headers=None): + """ Parses an HTTP WWW-Authentication Bearer challenge from a server. """ + self.source_authority = self._validate_request_uri(request_uri) + self.source_uri = request_uri + self._parameters = {} + + # get the scheme of the challenge and remove from the challenge string + trimmed_challenge = self._validate_challenge(challenge) + split_challenge = trimmed_challenge.split(" ", 1) + self.scheme = split_challenge[0] + trimmed_challenge = split_challenge[1] + + # split trimmed challenge into comma-separated name=value pairs. Values are expected + # to be surrounded by quotes which are stripped here. + for item in trimmed_challenge.split(","): + # process name=value pairs + comps = item.split("=") + if len(comps) == 2: + key = comps[0].strip(' "') + value = comps[1].strip(' "') + if key: + self._parameters[key] = value + + # minimum set of parameters + if not self._parameters: + raise ValueError("Invalid challenge parameters") + + # must specify authorization or authorization_uri + if "authorization" not in self._parameters and "authorization_uri" not in self._parameters: + raise ValueError("Invalid challenge parameters") + + # if the response headers were supplied + if response_headers: + # get the message signing key and message key encryption key from the headers + self.server_signature_key = response_headers.get("x-ms-message-signing-key", None) + self.server_encryption_key = response_headers.get("x-ms-message-encryption-key", None) + + def is_bearer_challenge(self): + """ Tests whether the HttpChallenge a Bearer challenge. + rtype: bool """ + if not self.scheme: + return False + + return self.scheme.lower() == "bearer" + + def is_pop_challenge(self): + """ Tests whether the HttpChallenge is a proof of possession challenge. + rtype: bool """ + if not self.scheme: + return False + + return self.scheme.lower() == "pop" + + def get_value(self, key): + return self._parameters.get(key) + + def get_authorization_server(self): + """ Returns the URI for the authorization server if present, otherwise empty string. """ + value = "" + for key in ["authorization_uri", "authorization"]: + value = self.get_value(key) or "" + if value: + break + return value + + def get_resource(self): + """ Returns the resource if present, otherwise empty string. """ + return self.get_value("resource") or "" + + def get_scope(self): + """ Returns the scope if present, otherwise empty string. """ + return self.get_value("scope") or "" + + def supports_pop(self): + """ Returns True if challenge supports pop token auth else False """ + return self._parameters.get("supportspop", "").lower() == "true" + + def supports_message_protection(self): + """ Returns True if challenge vault supports message protection """ + return self.supports_pop() and self.server_encryption_key and self.server_signature_key + + def _validate_challenge(self, challenge): + """ Verifies that the challenge is a valid auth challenge and returns the key=value pairs. """ + if not challenge: + raise ValueError("Challenge cannot be empty") + + return challenge.strip() + + # pylint: disable=no-self-use + def _validate_request_uri(self, uri): + """ Extracts the host authority from the given URI. """ + if not uri: + raise ValueError("request_uri cannot be empty") + + uri = parse.urlparse(uri) + if not uri.netloc: + raise ValueError("request_uri must be an absolute URI") + + if uri.scheme.lower() not in ["http", "https"]: + raise ValueError("request_uri must be HTTP or HTTPS") + + return uri.netloc diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge_cache.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge_cache.py new file mode 100644 index 000000000000..07cda1366aa8 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/_shared/http_challenge_cache.py @@ -0,0 +1,89 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import threading + +try: + import urllib.parse as parse +except ImportError: + import urlparse as parse # type: ignore + +try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = False + +if TYPE_CHECKING: + # pylint: disable=unused-import + from typing import Dict + from .http_challenge import HttpChallenge + + +_cache = {} # type: Dict[str, HttpChallenge] +_lock = threading.Lock() + + +def get_challenge_for_url(url): + """ Gets the challenge for the cached URL. + :param url: the URL the challenge is cached for. + :rtype: HttpBearerChallenge """ + + if not url: + raise ValueError("URL cannot be None") + + key = _get_cache_key(url) + + with _lock: + return _cache.get(key) + + +def _get_cache_key(url): + """Use the URL's netloc as cache key except when the URL specifies the default port for its scheme. In that case + use the netloc without the port. That is to say, https://foo.bar and https://foo.bar:443 are considered equivalent. + + This equivalency prevents an unnecessary challenge when using Key Vault's paging API. The Key Vault client doesn't + specify ports, but Key Vault's next page links do, so a redundant challenge would otherwise be executed when the + client requests the next page.""" + + parsed = parse.urlparse(url) + if parsed.scheme == "https" and parsed.port == 443: + return parsed.netloc[:-4] + return parsed.netloc + + +def remove_challenge_for_url(url): + """ Removes the cached challenge for the specified URL. + :param url: the URL for which to remove the cached challenge """ + if not url: + raise ValueError("URL cannot be empty") + + url = parse.urlparse(url) + + with _lock: + del _cache[url.netloc] + + +def set_challenge_for_url(url, challenge): + """ Caches the challenge for the specified URL. + :param url: the URL for which to cache the challenge + :param challenge: the challenge to cache """ + if not url: + raise ValueError("URL cannot be empty") + + if not challenge: + raise ValueError("Challenge cannot be empty") + + src_url = parse.urlparse(url) + if src_url.netloc != challenge.source_authority: + raise ValueError("Source URL and Challenge URL do not match") + + with _lock: + _cache[src_url.netloc] = challenge + + +def clear(): + """ Clears the cache. """ + + with _lock: + _cache.clear() diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/__init__.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/__init__.py index 652f08e501f6..44967833f2df 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/__init__.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/__init__.py @@ -3,6 +3,5 @@ # Licensed under the MIT License. # ------------------------------------ from ._client import SecretClient -from .._models import Secret, SecretAttributes, DeletedSecret __all__ = ["SecretClient"] diff --git a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_client.py b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_client.py index 92502763e6cd..d7cf860c4309 100644 --- a/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-secrets/azure/keyvault/secrets/aio/_client.py @@ -8,10 +8,10 @@ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError from azure.keyvault.secrets._models import Secret, DeletedSecret, SecretAttributes -from ._internal import _AsyncKeyVaultClientBase, AsyncPagingAdapter +from .._shared import AsyncKeyVaultClientBase, AsyncPagingAdapter -class SecretClient(_AsyncKeyVaultClientBase): +class SecretClient(AsyncKeyVaultClientBase): """SecretClient is a high-level interface for managing a vault's secrets. Example: diff --git a/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client.py b/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client.py index c0ed96a197ce..4ce440dea4f6 100644 --- a/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client.py +++ b/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client.py @@ -7,7 +7,7 @@ except ImportError: TYPE_CHECKING = False -from azure.keyvault.secrets._internal import _KeyVaultClientBase +from azure.keyvault.secrets._shared import KeyVaultClientBase from azure.keyvault.secrets import SecretClient if TYPE_CHECKING: @@ -18,7 +18,7 @@ from typing import Any, Optional -class VaultClient(_KeyVaultClientBase): +class VaultClient(KeyVaultClientBase): def __init__(self, vault_url, credential, config=None, transport=None, api_version=None, **kwargs): # type: (str, TokenCredential, Configuration, Optional[HttpTransport], Optional[str], **Any) -> None super(VaultClient, self).__init__( diff --git a/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client_async.py b/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client_async.py index 26208474b62d..f51f22570077 100644 --- a/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client_async.py +++ b/sdk/keyvault/azure-keyvault-secrets/tests/secrets_vault_client_async.py @@ -10,9 +10,8 @@ from azure.core.pipeline.transport import AsyncioRequestsTransport, HttpTransport from msrest.serialization import Model -from azure.keyvault.secrets._generated import KeyVaultClient +from azure.keyvault.secrets._shared import AsyncKeyVaultClientBase from azure.keyvault.secrets.aio import SecretClient -from azure.keyvault.secrets.aio._internal import _AsyncKeyVaultClientBase if TYPE_CHECKING: try: @@ -24,7 +23,7 @@ KEY_VAULT_SCOPE = "https://vault.azure.net/.default" -class VaultClient(_AsyncKeyVaultClientBase): +class VaultClient(AsyncKeyVaultClientBase): def __init__( self, vault_url: str,