From 3cc82bd990673fd0e6ae65239d9ba608478778ea Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Mon, 4 May 2020 14:36:18 -0700 Subject: [PATCH] split client_credential.py --- .../azure/identity/_credentials/__init__.py | 3 +- .../identity/_credentials/certificate.py | 52 ++++++++++++++++ ...{client_credential.py => client_secret.py} | 44 +------------- .../identity/_credentials/environment.py | 3 +- .../identity/aio/_credentials/__init__.py | 3 +- .../{client_credential.py => certificate.py} | 50 +--------------- .../aio/_credentials/client_secret.py | 59 +++++++++++++++++++ .../identity/aio/_credentials/environment.py | 3 +- 8 files changed, 123 insertions(+), 94 deletions(-) create mode 100644 sdk/identity/azure-identity/azure/identity/_credentials/certificate.py rename sdk/identity/azure-identity/azure/identity/_credentials/{client_credential.py => client_secret.py} (52%) rename sdk/identity/azure-identity/azure/identity/aio/_credentials/{client_credential.py => certificate.py} (53%) create mode 100644 sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/__init__.py b/sdk/identity/azure-identity/azure/identity/_credentials/__init__.py index 88c94d65bd60..cd0068cc3cd8 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/__init__.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/__init__.py @@ -4,8 +4,9 @@ # ------------------------------------ from .authorization_code import AuthorizationCodeCredential from .browser import InteractiveBrowserCredential +from .certificate import CertificateCredential from .chained import ChainedTokenCredential -from .client_credential import CertificateCredential, ClientSecretCredential +from .client_secret import ClientSecretCredential from .default import DefaultAzureCredential from .environment import EnvironmentCredential from .managed_identity import ManagedIdentityCredential diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py b/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py new file mode 100644 index 000000000000..3ed84cd335a0 --- /dev/null +++ b/sdk/identity/azure-identity/azure/identity/_credentials/certificate.py @@ -0,0 +1,52 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from typing import TYPE_CHECKING + +from .._authn_client import AuthnClient +from .._base import CertificateCredentialBase + +if TYPE_CHECKING: + from azure.core.credentials import AccessToken + from typing import Any + + +class CertificateCredential(CertificateCredentialBase): + """Authenticates as a service principal using a certificate. + + :param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID. + :param str client_id: the service principal's client ID + :param str certificate_path: path to a PEM-encoded certificate file including the private key. + + :keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com', + the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities` + defines authorities for other clouds. + :keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate + requires a different encoding, pass appropriately encoded bytes instead. + :paramtype password: str or bytes + """ + + def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument + # type: (*str, **Any) -> AccessToken + """Request an access token for `scopes`. + + .. note:: This method is called by Azure SDK clients. It isn't intended for use in application code. + + :param str scopes: desired scopes for the access token. This method requires at least one scope. + :rtype: :class:`azure.core.credentials.AccessToken` + :raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message`` + attribute gives a reason. Any error response from Azure Active Directory is available as the error's + ``response`` attribute. + """ + if not scopes: + raise ValueError("'get_token' requires at least one scope") + + token = self._client.get_cached_token(scopes) + if not token: + data = self._get_request_data(*scopes) + token = self._client.request_token(scopes, form_data=data) + return token + + def _get_auth_client(self, tenant_id, **kwargs): + return AuthnClient(tenant=tenant_id, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/client_credential.py b/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py similarity index 52% rename from sdk/identity/azure-identity/azure/identity/_credentials/client_credential.py rename to sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py index 1ee646d80d1c..f8dbd45bce9c 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/client_credential.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/client_secret.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. # ------------------------------------ from .._authn_client import AuthnClient -from .._base import ClientSecretCredentialBase, CertificateCredentialBase +from .._base import ClientSecretCredentialBase try: from typing import TYPE_CHECKING @@ -12,7 +12,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports - from typing import Any, Mapping + from typing import Any from azure.core.credentials import AccessToken @@ -53,43 +53,3 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument data = dict(self._form_data, scope=" ".join(scopes)) token = self._client.request_token(scopes, form_data=data) return token - - -class CertificateCredential(CertificateCredentialBase): - """Authenticates as a service principal using a certificate. - - :param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID. - :param str client_id: the service principal's client ID - :param str certificate_path: path to a PEM-encoded certificate file including the private key. - - :keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com', - the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities` - defines authorities for other clouds. - :keyword password: The certificate's password. If a unicode string, it will be encoded as UTF-8. If the certificate - requires a different encoding, pass appropriately encoded bytes instead. - :paramtype password: str or bytes - """ - - def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument - # type: (*str, **Any) -> AccessToken - """Request an access token for `scopes`. - - .. note:: This method is called by Azure SDK clients. It isn't intended for use in application code. - - :param str scopes: desired scopes for the access token. This method requires at least one scope. - :rtype: :class:`azure.core.credentials.AccessToken` - :raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message`` - attribute gives a reason. Any error response from Azure Active Directory is available as the error's - ``response`` attribute. - """ - if not scopes: - raise ValueError("'get_token' requires at least one scope") - - token = self._client.get_cached_token(scopes) - if not token: - data = self._get_request_data(*scopes) - token = self._client.request_token(scopes, form_data=data) - return token - - def _get_auth_client(self, tenant_id, **kwargs): - return AuthnClient(tenant=tenant_id, **kwargs) diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py index 3cea7422907f..dc37abca83c1 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/environment.py @@ -6,7 +6,8 @@ from .. import CredentialUnavailableError from .._constants import EnvironmentVariables -from .client_credential import CertificateCredential, ClientSecretCredential +from .certificate import CertificateCredential +from .client_secret import ClientSecretCredential from .user_password import UsernamePasswordCredential diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/__init__.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/__init__.py index 5b06446c4775..cf63acbd84d6 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/__init__.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/__init__.py @@ -7,7 +7,8 @@ from .default import DefaultAzureCredential from .environment import EnvironmentCredential from .managed_identity import ManagedIdentityCredential -from .client_credential import CertificateCredential, ClientSecretCredential +from .certificate import CertificateCredential +from .client_secret import ClientSecretCredential from .shared_cache import SharedTokenCacheCredential from .azure_cli import AzureCliCredential diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_credential.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py similarity index 53% rename from sdk/identity/azure-identity/azure/identity/aio/_credentials/client_credential.py rename to sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py index 8801347f3c31..300728f221f1 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_credential.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/certificate.py @@ -6,59 +6,13 @@ from .base import AsyncCredentialBase from .._authn_client import AsyncAuthnClient -from ..._base import ClientSecretCredentialBase, CertificateCredentialBase +from ..._base import CertificateCredentialBase if TYPE_CHECKING: - from typing import Any, Mapping + from typing import Any from azure.core.credentials import AccessToken -class ClientSecretCredential(ClientSecretCredentialBase, AsyncCredentialBase): - """Authenticates as a service principal using a client ID and client secret. - - :param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID. - :param str client_id: the service principal's client ID - :param str client_secret: one of the service principal's client secrets - - :keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com', - the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities` - defines authorities for other clouds. - """ - - def __init__(self, tenant_id: str, client_id: str, client_secret: str, **kwargs: "Any") -> None: - super(ClientSecretCredential, self).__init__(tenant_id, client_id, client_secret, **kwargs) - self._client = AsyncAuthnClient(tenant=tenant_id, **kwargs) - - async def __aenter__(self): - await self._client.__aenter__() - return self - - async def close(self): - """Close the credential's transport session.""" - - await self._client.__aexit__() - - async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument - """Asynchronously request an access token for `scopes`. - - .. note:: This method is called by Azure SDK clients. It isn't intended for use in application code. - - :param str scopes: desired scopes for the access token. This method requires at least one scope. - :rtype: :class:`azure.core.credentials.AccessToken` - :raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message`` - attribute gives a reason. Any error response from Azure Active Directory is available as the error's - ``response`` attribute. - """ - if not scopes: - raise ValueError("'get_token' requires at least one scope") - - token = self._client.get_cached_token(scopes) - if not token: - data = dict(self._form_data, scope=" ".join(scopes)) - token = await self._client.request_token(scopes, form_data=data) - return token # type: ignore - - class CertificateCredential(CertificateCredentialBase, AsyncCredentialBase): """Authenticates as a service principal using a certificate. diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py new file mode 100644 index 000000000000..60a51bb037e5 --- /dev/null +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/client_secret.py @@ -0,0 +1,59 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from typing import TYPE_CHECKING + +from .base import AsyncCredentialBase +from .._authn_client import AsyncAuthnClient +from ..._base import ClientSecretCredentialBase + +if TYPE_CHECKING: + from typing import Any + from azure.core.credentials import AccessToken + + +class ClientSecretCredential(ClientSecretCredentialBase, AsyncCredentialBase): + """Authenticates as a service principal using a client ID and client secret. + + :param str tenant_id: ID of the service principal's tenant. Also called its 'directory' ID. + :param str client_id: the service principal's client ID + :param str client_secret: one of the service principal's client secrets + + :keyword str authority: Authority of an Azure Active Directory endpoint, for example 'login.microsoftonline.com', + the authority for Azure Public Cloud (which is the default). :class:`~azure.identity.KnownAuthorities` + defines authorities for other clouds. + """ + + def __init__(self, tenant_id: str, client_id: str, client_secret: str, **kwargs: "Any") -> None: + super(ClientSecretCredential, self).__init__(tenant_id, client_id, client_secret, **kwargs) + self._client = AsyncAuthnClient(tenant=tenant_id, **kwargs) + + async def __aenter__(self): + await self._client.__aenter__() + return self + + async def close(self): + """Close the credential's transport session.""" + + await self._client.__aexit__() + + async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken": # pylint:disable=unused-argument + """Asynchronously request an access token for `scopes`. + + .. note:: This method is called by Azure SDK clients. It isn't intended for use in application code. + + :param str scopes: desired scopes for the access token. This method requires at least one scope. + :rtype: :class:`azure.core.credentials.AccessToken` + :raises ~azure.core.exceptions.ClientAuthenticationError: authentication failed. The error's ``message`` + attribute gives a reason. Any error response from Azure Active Directory is available as the error's + ``response`` attribute. + """ + if not scopes: + raise ValueError("'get_token' requires at least one scope") + + token = self._client.get_cached_token(scopes) + if not token: + data = dict(self._form_data, scope=" ".join(scopes)) + token = await self._client.request_token(scopes, form_data=data) + return token # type: ignore diff --git a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py index 84c3a7e45d63..7e1197d702c2 100644 --- a/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py +++ b/sdk/identity/azure-identity/azure/identity/aio/_credentials/environment.py @@ -7,7 +7,8 @@ from ... import CredentialUnavailableError from ..._constants import EnvironmentVariables -from .client_credential import CertificateCredential, ClientSecretCredential +from .certificate import CertificateCredential +from .client_secret import ClientSecretCredential from .base import AsyncCredentialBase if TYPE_CHECKING: