如何在 Azure 上对 Python 应用进行身份验证和授权How to authenticate and authorize Python apps on Azure
01/19/2021
本文内容
大多数部署到 Azure 的云应用程序都需要访问其他 Azure 资源,如存储、数据库、存储的机密等等。Most cloud applications deployed to Azure need to access other Azure resources such as storage, databases, stored secrets, and so on. 若要访问这些资源,必须对应用程序进行身份验证和授权:To access those resources, the application must be both authenticated and authorized:
身份验证通过 Azure Active Directory 验证应用的标识。Authentication verifies the app's identity with Azure Active Directory.
授权确定经过身份验证的应用可以对任何给定资源执行哪些操作。Authorization determines which operations the authenticated app can perform on any given resource. 授权操作由分配给该资源的应用标识的角色定义。The authorized operations are defined by the roles assigned to the app identity for that resource. 在少数情况下(如 Azure Key Vault),授权还由分配给应用标识的其他访问策略确定。In a few cases, such as Azure Key Vault, authorization is also determined by additional access policies that are assigned to the app identity.
本文介绍了身份验证和授权的详细信息:This article explains the details of authentication and authorization:
如何分配应用标识How to assign an app identity
如何向标识授予权限How to grant permissions to an identity
身份验证和授权的发生方式和时间How and when authentication and authorization occur
应用使用 Azure 库对 Azure 进行身份验证的不同方法。The different means through which an app authenticates with Azure using the Azure libraries. 建议使用 DefaultAzureCredential,但这不是必需的。Using DefaultAzureCredential is recommended, but not required.
如何分配应用标识How to assign an app identity
在 Azure 上,应用标识由服务主体定义。On Azure, an app identity is defined by a service principal. (服务主体是特定类型的“安全主体”,用于标识应用或服务,即一段代码,而不是一个用户或一组用户。)(A service principal is a specific type of "security principal" that's used to identify an app or service, which is to say, a piece of code, as opposed to a human user or group of users.)
涉及的服务主体取决于应用的运行位置,如以下各节中所述。The service principal involved depends on where the app is running, as described in the following sections.
在 Azure 上运行应用时的标识Identity when running the app on Azure
在云中(例如在生产环境中)运行时,应用最常使用系统分配的托管标识(以前称为 MSI)。When running in the cloud (for example, in production), an app most commonly uses a system-assigned managed identity (formerly referred to as "MSI"). 使用托管标识,可以在为资源分配角色和权限时使用应用的名称。With a managed identity, you use the app's name when assigning roles and permissions for resources. Azure 自动管理基础服务主体,并使用其他 Azure 资源自动对应用进行身份验证。Azure automatically manages the underlying service principal and automatically authenticates the app with those other Azure resources. 因此,你无需直接处理服务主体。As a result, you don't need to handle the service principal directly. 此外,应用代码永远无需处理 Azure 资源的访问令牌、机密或连接字符串,从而降低了此类信息可能被泄漏或以其他方式遭到入侵的风险。Furthermore, your app code never needs to handle access tokens, secrets, or connection strings for Azure resources, which reduces the risk that any such information might be leaked or otherwise compromised.
托管标识的配置取决于用于托管应用的服务。Configuring managed identity depends on the service you use to host your app. 请参阅支持托管标识的服务一文,以获取指向每个服务的说明的链接。Refer to the article, Services that support managed identity for links to instructions for each service. 例如,对于部署到 Azure 应用服务的 Web 应用,可通过 Azure 门户中的“标识” > “系统分配”选项或使用 Azure CLI 中的 az webapp identity assign 命令启用托管标识 。For web apps deployed to Azure App Service, for example, you enable managed identity through the Identity > System assigned option in the Azure portal, or by using the az webapp identity assign command in the Azure CLI.
如果无法使用托管标识,请改为手动将应用程序注册到 Azure Active Directory。If you can't use managed identity, you instead manually register the application with Azure Active Directory. 注册操作可为应用分配服务主体,供你在分配角色和权限时使用。Registration assigns a service principal to the app, which you use when assigning roles and permissions. 有关详细信息,请参阅注册应用程序。For more information, see Register an application.
在本地运行应用时的标识Identity when running the app locally
在开发过程中,你通常希望在开发人员工作站上运行和调试应用代码,同时让此代码仍可访问云中的 Azure 资源。During development, you often want to run and debug your app code on a developer workstation while still having that code access Azure resources in the cloud. 在这种情况下,可以通过 Azure Active Directory 创建一个单独的服务主体,专门用于本地开发。In this case, you create a separate service principal through Azure Active Directory specifically for local development. 再次将角色和权限分配给该服务主体,以获得相关资源。You again assign roles and permissions to this service principal for the resources in question. 通常,你授权此开发标识仅访问非生产资源。Typically, you authorize this development identity to access only non-production resources.
要详细了解如何创建本地服务主体并使其可供 Azure 库使用,请参阅配置本地开发环境。For details on creating the local service principal and making it available to the Azure libraries, see Configure your local development environment. 完成这个一次性配置后,你可在本地和云中运行相同的应用代码,而无需进行任何特定于环境的修改。Once you've completed this one-time configuration, you can run the same app code locally and in the cloud without any environment-specific modifications.
每个开发人员都应具有自己的服务主体,这些服务主体可以安全地存储在他们的工作站上的用户帐户中,且永远不要将其存储在源代码管理存储库中。Each developer should have his or her own service principal that's secured within their user account on their workstation and never stored in a source control repository. 如有任一个服务主体被窃取或泄露,你可轻松删除它以撤销其所有权限,然后为该开发人员重新创建服务主体。If any one service principal is ever stolen or compromised, you can easily delete it to revoke all of its permissions, and then recreate the service principal for that developer. 有关详细信息,请参阅如何管理服务主体。
备注
尽管可以使用自己的 Azure 用户凭据运行应用,但这样做并不能帮助你创建将应用部署到云时所需的特定资源权限。Although it's possible to run an app using your own Azure user credential, doing so doesn't help you establish the specific resource permissions that your app needs when deployed to the cloud. 最好是设置用于开发的服务主体,并为其分配所需的角色和权限,然后你可以使用已部署应用的托管标识或服务主体复制这些角色和权限。It's much better to set up a service principal for development and assign it the necessary roles and permissions, which you can then replicate using with the deployed app's managed identity or service principal.
为标识分配角色和权限Assign roles and permissions to an identity
了解应用在 Azure 上和在本地运行时的标识后,就可以使用基于角色的访问控制 (RBAC) 通过 Azure 门户或 Azure CLI 授予权限。Once you know the identities for the app both on Azure and when running locally, you use role-based access control (RBAC) to grant permissions through the Azure portal or the Azure CLI.
身份验证和授权何时发生?When does authentication and authorization occur?
使用用于 Python 的 Azure 库 (SDK) 编写应用代码时,请使用以下模式访问 Azure 资源:When writing app code using the Azure libraries (SDK) for Python, you use the following pattern to access Azure resources:
使用本文后面介绍的方法之一来获取用于描述应用标识的凭据。Acquire a credential, which describes the app identity, using one of the methods described later in this article.
使用该凭据获取目标资源的客户端对象。Use the credential to acquire a client object for the resource of interest. (每种类型的资源在 Azure 库中都有其自己的客户端对象,你可以向其提供资源的 URL。)(Each type of resource has its own client object in the Azure libraries, to which you provide the resource's URL.)
尝试通过客户端对象访问或修改资源,该对象将生成对资源的 REST API 的 HTTP 请求。Attempt to access or modify the resource through the client object, which generates an HTTP request to the resource's REST API. API 调用是 Azure 随后对应用标识进行身份验证和检查授权的点。The API call is the point at which Azure then both authenticates the app identity and checks authorization.
以下代码通过尝试访问 Azure Key Vault 来描述和演示这些步骤。The following code describes and demonstrates these steps by attempting to access Azure Key Vault.
import os
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
# Acquire the resource URL. In this code we assume the resource URL is in an
# environment variable, KEY_VAULT_URL in this case.
vault_url = os.environ["KEY_VAULT_URL"]
# Acquire a credential object for the app identity. When running in the cloud,
# DefaultAzureCredential uses the app's managed identity (MSI) or user-assigned service principal.
# When run locally, DefaultAzureCredential relies on environment variables named
# AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID.
credential = DefaultAzureCredential()
# Acquire an appropriate client object for the resource identified by the URL. The
# client object only stores the given credential at this point but does not attempt
# to authenticate it.
#
# **NOTE**: SecretClient here is only an example; the same process applies to all
# other Azure client libraries.
secret_client = SecretClient(vault_url=vault_url, credential=credential)
# Attempt to perform an operation on the resource using the client object (in
# this case, retrieve a secret from Key Vault). The operation fails for any of
# the following reasons:
#
# 1. The information in the credential object is invalid (for example, the AZURE_CLIENT_ID
# environment variable cannot be found).
# 2. The app identity cannot be authenticated using the information in the credential object.
# 3. The app identity is not authorized to perform the requested operation on the
# resource (identified in this case by the vault_url.
retrieved_secret = secret_client.get_secret("secret-name-01")
同样,在代码通过客户端对象向 Azure REST API 发出特定请求之前,不会进行身份验证或授权。Again, no authentication or authorization takes place until your code makes a specific request to the Azure REST API through a client object. 用于创建 DefaultAzureCredential 的语句(请参阅下一节)仅在内存中创建一个客户端对象,但不执行其他检查。The statement to create the DefaultAzureCredential [see the next section) only creates a client-side object in memory, but performs no other checks.
创建 SDK SecretClient 对象也不涉及与相关资源的通信。Creating the SDK SecretClient object also involves no communication with the resource in question. SecretClient 对象只是基础 Azure REST API 的包装器,仅存在于应用的运行时内存中。The SecretClient object is just a wrapper around the underlying Azure REST API and exists only in the app's runtime memory.
仅当代码调用 get_secret 方法时,客户端对象才会生成对 Azure 的相应 REST API 调用。It's only when the code calls the get_secret method that the client object generates the appropriate REST API call to Azure. 然后,get_secret 的 Azure 终结点会对调用方的标识进行身份验证并检查授权。Azure's endpoint for get_secret then authenticates the caller's identity and checks authorization.
使用 DefaultAzureCredential 进行身份验证Authenticate with DefaultAzureCredential
For most applications, the DefaultAzureCredential class from the azure-identity library provides the simplest and recommended means of authentication.
DefaultAzureCredential 在云中自动使用应用的托管标识 (MSI),并在本地运行时从环境变量自动加载本地服务主体(如 配置适用于 Azure 的本地 Python 开发环境 - 配置身份验证中所述)。DefaultAzureCredential automatically uses the app's managed identity (MSI) in the cloud, and automatically loads a local service principal from environment variables when running locally (as described on Configure your local Python dev environment for Azure - Configure authentication).
import os
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
# Acquire the resource URL
vault_url = os.environ["KEY_VAULT_URL"]
# Acquire a credential object
credential = DefaultAzureCredential()
# Acquire a client object
secret_client = SecretClient(vault_url=vault_url, credential=credential)
# Attempt to perform an operation
retrieved_secret = secret_client.get_secret("secret-name-01")
前面的代码在访问 Azure Key Vault 时使用 DefaultAzureCredential 对象,其中 Key Vault 的 URL 可在名为 KEY_VAULT_URL 的环境变量中获得。The preceding code uses a DefaultAzureCredential object when accessing Azure Key Vault, where the URL of the Key Vault is available in an environment variable named KEY_VAULT_URL. 此代码明确实现典型的库使用模式:获取凭据对象,为 Azure 资源创建适当的客户端对象,然后尝试使用该客户端对象对该资源执行操作。The code clearly implements the typical library usage pattern: acquire a credential object, create an appropriate client object for the Azure resource, then attempt to perform an operation on that resource using that client object. 同样,在最后一步之前不会进行身份验证和授权。Again, authentication and authorization don't happen until this final step.
代码部署到 Azure 并在其中运行时,DefaultAzureCredential 会自动使用系统分配的托管标识 (MSI),你可以在托管该标识的任何服务中为应用启用该标识。When code is deployed to and running on Azure, DefaultAzureCredential automatically uses the system-assigned managed identity (MSI) that you can enable for the app within whatever service is hosting it. 使用 Azure 门户或 Azure CLI 将特定资源(例如,Azure 存储或 Azure Key Vault)的权限分配给该标识。Permissions for specific resources, such as Azure Storage or Azure Key Vault, are assigned to that identity using the Azure portal or the Azure CLI. 在这些情况下,此 Azure 托管的标识将最大限度地提高安全性,因为你从不在代码中处理显式服务主体。In these cases, this Azure-managed identity maximizes security because you don't ever deal with an explicit service principal in your code.
在本地运行代码时,DefaultAzureCredential 会自动使用名为 AZURE_TENANT_ID、AZURE_CLIENT_ID 和 AZURE_CLIENT_SECRET 的环境变量所描述的服务主体。When you run your code locally, DefaultAzureCredential automatically uses the service principal described by the environment variables named AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET. 然后,在调用 API 终结点时,此客户端对象会在 HTTP 请求标头中(以安全的方式)包含这些值。The client object then includes these values (securely) in the HTTP request header when calling the API endpoint. 在本地或云中运行时,无需更改任何代码。No code changes are necessary when running locally or in the cloud. For details on creating the service principal and setting up the environment variables, see Configure your local Python dev environment for Azure - Configure authentication.
在这两种情况下,必须向所涉及的标识分配适当资源的权限。In both cases, the identity involved must be assigned permissions for the appropriate resource. 如何分配角色权限中介绍了常规流程;你可在各项服务的文档中找到具体信息。The general process is described on How to assign role permissions; specifics can be found in the documentation for the individual services. 要详细了解前面代码所需的 Key Vault 权限,请参阅使用访问控制策略提供 Key Vault 身份验证。For details on Key Vault permissions, for example, as would be needed for the previous code, see Provide Key Vault authentication with an access control policy.
将 DefaultAzureCredential 与 SDK 管理库配合使用Using DefaultAzureCredential with SDK management libraries
DefaultAzureCredential 适用于较新版本的 Azure SDK 管理库,即名称中带有“mgmt”且也显示在使用 azure.core 的库列表中的“资源管理”库。DefaultAzureCredential works with newer versions of the Azure SDK management libraries, that is, those "Resource Management" libraries with "mgmt" in their names that also appear on the Libraries using azure.core list. (此外,已更新的库的 pypi 页面通常包含“凭据系统进行了彻底更新和优化”这一行内容,以指示所作更改。)(Also, the pypi page for an updated library usually includes the line, "Credential system has been completely revamped" to indicate the change.)
例如,可将 DefaultAzureCredential 与 azure-mgmt-resource 的版本 15.0.0 或更高版本结合使用:For example, you can use DefaultAzureCredential with version 15.0.0 or higher of azure-mgmt-resource:
from azure.identity import DefaultAzureCredential
from azure.mgmt.resource import SubscriptionClient
credential = DefaultAzureCredential()
subscription_client = SubscriptionClient(credential)
sub_list = subscription_client.subscriptions.list()
print(list(sub_list))
如果库尚未更新,则使用 DefaultAzureCredential 的代码将假定“对象没有 signed-session 特性”,如下一部分所述。If the library has not been updated, code using DefaultAzureCredential will given the "object has no attribute 'signed-session'" as described in the next section.
凭据“对象没有特性 'signed_session'”Credential "object has no attribute 'signed_session'"
如果尝试将 DefaultAzureCredential(或 AzureCliCredential 以及来自 azure.identity 的其他凭据对象)用于尚未更新为使用 azure.core 的库,那么通过客户端对象的调用会失败,并出现信息相对模糊的错误:“'DefaultAzureCredential 对象没有特性 'signed_session'”。If you attempt to use DefaultAzureCredential (or AzureCliCredential and other credential objects from azure.identity) with a library that has not been updated to use azure.core, calls through a client object fail with the rather vague error, "'DefaultAzureCredential' object has no attribute 'signed_session'". 例如,如果将上一部分中的代码与低于版本 15 的 azure-mgmt-resource 库结合使用,就会遇到此类错误。You'd encounter such a failure, ror example, if you use the code in the preceding section with an azure-mgmt-resource library below version 15.
出现此错误的原因是,SDK 管理库的非 azure.core 版本假定凭据对象包含 signed_session 属性,而 DefaultAzureCredential 以及来自 azure.identity 的其他凭据对象上不存在这个属性。This error happens because non-azure.core versions of SDK management libraries assume that the credential object contains a signed_session property, which is not present on DefaultAzureCredential and other credential objects from azure.identity.
如果要使用的管理库尚未更新,可以使用以下替代方法:If the management library you want to use has not yet been updated, then you can use the following alternate methods:
使用本文后续部分中所述的其他身份验证方法之一,这些方法非常适用于仅使用 SDK 管理库且不会部署到云的代码,在这种情况下,你只能依赖于本地服务主体。Use one of the other authentication methods describe in subsequent sections of this article, which can work well for code that uses only SDK management libraries and that won't be deployed to the cloud, in which case you can rely on local service principals only.
使用 Azure SDK 工程团队成员提供的 CredentialWrapper 类 (cred_wrapper.py),而不是 DefaultAzureCredential。Instead of DefaultAzureCredential, use the CredentialWrapper class (cred_wrapper.py) that's provided by a member of the Azure SDK engineering team. 当所需的管理库可用后,请切换回 DefaultAzureCredential。Once the desired management library is available, switch back to DefaultAzureCredential. 此方法的优点是,可以将同一凭据同时用于 SDK 客户端和管理库,并且它在本地和云中都有效。This method has the advantage that you can use the same credential with both SDK client and management libraries, and it works both locally and in the cloud.
假定已将 cred_wrapper.py 的副本下载到项目文件夹中,则前面的代码将如下所示:Assuming that you've downloaded a copy of cred_wrapper.py into your project folder, the previous code would appear as follows:
from cred_wrapper import CredentialWrapper
from azure.mgmt.resource import SubscriptionClient
credential = CredentialWrapper()
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
同样,当更新的管理库可用后,可直接使用 DefaultAzureCredential,如原始代码示例中所示。Again, once updated management libraries are available, you can use DefaultAzureCredential directly as shown in the original code example.
其他身份验证方法Other authentication methods
尽管 DefaultAzureCredential 是大多数情况下建议使用的身份验证方法,但其他方法也可用,有以下注意事项:Although DefaultAzureCredential is the recommended authentication method for most scenarios, other methods are available with the following caveats:
大多数方法适用于显式服务主体,并且不会利用部署到云的代码的托管标识。Most of the methods work with explicit service principals and don't take advantage of managed identity for code that's deployed to the cloud. 与生产代码一起使用时,必须为云应用程序管理和维护不同的服务主体。When used with production code, then, you must manage and maintain distinct service principals for your cloud applications.
某些方法(例如基于 CLI 的身份验证)仅适用于本地脚本,不能与生产代码一起使用。Some methods, such as CLI-based authentication, work only with local scripts and cannot be used with production code. 对于开发工作来说,基于 CLI 的身份验证非常便捷,因为它使用 Azure 登录的权限,不需要显式角色分配。CLI-based authentication is convenient for development work because it uses the permissions of your Azure login and doesn't require explicit role assignments.
部署到云的应用程序的服务主体在 Active Directory 订阅中进行管理。Service principals for applications deployed to the cloud are managed in your subscriptions Active Directory. 有关详细信息,请参阅如何管理服务主体。
在所有情况下,相应的服务主体或用户必须对相关资源和操作具有适当的权限。In all cases, the appropriate service principal or user must have appropriate permissions for the resources and operation in question.
使用 JSON 文件进行身份验证Authenticate with a JSON file
在此方法中,创建一个 JSON 文件(其中包含服务主体所需的凭据)。In this method, you create a JSON file that contains the necessary credentials for the service principal. 然后使用该文件创建 SDK 客户端对象。You then create an SDK client object using that file. 此方法既可在本地使用,也可在云中使用。This method can be used both locally and in the cloud.
使用以下格式创建 JSON 文件:Create a JSON file with the following format:
{
"subscriptionId": "",
"tenantId": "",
"clientId": "",
"clientSecret": "",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
将四个占位符替换为你的 Azure 订阅 ID、租户 ID、客户端 ID 和客户端密码。Replace the four placeholders with your Azure subscription ID, tenant ID, the client ID, and the client secret.
提示
如配置本地开发环境中所述,可以将 az ad sp create-for-rbac 命令与 --sdk-auth 参数一起使用,以直接生成此 JSON 格式。As explained in Configure your local dev environment, you can use the az ad sp create-for-rbac command with the --sdk-auth parameter to generate this JSON format directly.
使用名称(如 credentials.json)将此文件保存在可供代码访问的安全位置。Save the file with a name like credentials.json in a secure location that your code can access. 若要保护凭据,请确保从源代码管理中省略此文件,并且不要将其与其他开发人员共享。To keep your credentials secure, be sure to omit this file from source control and don't share it with other developers. 也就是说,服务主体的租户 ID、客户端 ID 和客户端密码应始终在开发工作站上保持隔离。That is, the tenant ID, client ID, and client secret of a service principal should always remain isolated on your development workstation.
创建一个名为 AZURE_AUTH_LOCATION 且值为 JSON 文件的路径的环境变量:Create an environment variable named AZURE_AUTH_LOCATION with the path to the JSON file as the value:
set AZURE_AUTH_LOCATION=../credentials.json
AZURE_AUTH_LOCATION="../credentials.json"
这些示例假定 JSON 文件名为 credentials.json,并且位于项目的父文件夹中。These examples assume the JSON file is named credentials.json and is located in the parent folder of your project.
Use the get_client_from_auth_file method to create the client object:
from azure.common.client_factory import get_client_from_auth_file
from azure.mgmt.resource import SubscriptionClient
# This form of get_client_from_auth_file relies on the AZURE_AUTH_LOCATION
# environment variable.
subscription_client = get_client_from_auth_file(SubscriptionClient)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
也可以使用 auth_path 参数在代码中直接指定路径,在这种情况下,不需要环境变量:You can alternately specify the path directly in code by using the auth_path argument, in which case the environment variable isn't needed:
subscription_client = get_client_from_auth_file(SubscriptionClient, auth_path="../credentials.json")
使用 JSON 字典进行身份验证Authenticate with a JSON dictionary
import os
from azure.common.client_factory import get_client_from_json_dict
from azure.mgmt.resource import SubscriptionClient
# Retrieve the IDs and secret to use in the JSON dictionary
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
tenant_id = os.environ["AZURE_TENANT_ID"]
client_id = os.environ["AZURE_CLIENT_ID"]
client_secret = os.environ["AZURE_CLIENT_SECRET"]
config_dict = {
"subscriptionId": subscription_id,
"tenantId": tenant_id,
"clientId": client_id,
"clientSecret": client_secret,
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}
subscription_client = get_client_from_json_dict(SubscriptionClient, config_dict)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
如上一部分所述,可以通过变量生成必要的 JSON 数据并调用 get_client_from_json_dict,而不是使用文件。Instead of using a file, as described in the previous section, you can build the necessary JSON data in a variable and call get_client_from_json_dict. 此代码假定已创建配置本地开发环境中所述的环境变量。This code assumes that you've created the environment variables described in Configure your local dev environment. 对于部署到云的代码,可以在服务器 VM 上创建这些环境变量,也可以在使用平台服务(如 Azure 应用服务和 Azure Functions)时将这些环境变量用作应用程序设置。For code deployed to the cloud, you can create these environment variables on your server VM or as application settings when using platform service like Azure App Service and Azure Functions.
还可以将值存储在 Azure Key Vault 中,并在运行时(而不是使用环境变量)检索这些值。You can also store values in Azure Key Vault and retrieve them at run time rather than using environment variables.
使用令牌凭据进行身份验证Authenticate with token credentials
可使用显式订阅、租户和客户端标识符以及客户端密码对 Azure 库进行身份验证。You can authenticate with the Azure libraries using explicit subscription, tenant, and client identifiers along with a client secret.
若要将使用 ServicePrincipalCredentials 的现有代码迁移到较新的库版本,请将使用的类替换为 ClientSecretCredential,如以下部分所示。To migrate existing code that uses ServicePrincipalCredentials to a newer library version, replace uses of this class with ClientSecretCredential as illustrated in the following sections. 请注意,两个构造函数的参数名称略有不同:tenant 变成 tenant_id,secret 变成 client_secret。Note the slight changes in the parameter names between the two constructors: tenant becomes tenant_id and secret becomes client_secret.
使用 ClientSecretCredential (azure.identity)Using ClientSecretCredential (azure.identity)
import os
from azure.mgmt.resource import SubscriptionClient
from azure.identity import ClientSecretCredential
# Retrieve the IDs and secret to use with ClientSecretCredential
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
tenant_id = os.environ["AZURE_TENANT_ID"]
client_id = os.environ["AZURE_CLIENT_ID"]
client_secret = os.environ["AZURE_CLIENT_SECRET"]
credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
在此方法中(再次用于基于 azure.core 的新库),将使用从安全存储(例如 Azure Key Vault 或环境变量)中获取的凭据创建 ClientSecretCredential 对象。In this method, which is again used with newer libraries based on azure.core, you create a ClientSecretCredential object using credentials obtained from secure storage such as Azure Key Vault or environment variables. 前面的代码假定已创建配置本地开发环境中所述的环境变量。The previous code assumes that you've created the environment variables described in Configure your local dev environment.
使用 ServicePrincipalCredentials (azure.common)Using ServicePrincipalCredentials (azure.common)
import os
from azure.mgmt.resource import SubscriptionClient
from azure.common.credentials import ServicePrincipalCredentials
# Retrieve the IDs and secret to use with ServicePrincipalCredentials
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
tenant_id = os.environ["AZURE_TENANT_ID"]
client_id = os.environ["AZURE_CLIENT_ID"]
client_secret = os.environ["AZURE_CLIENT_SECRET"]
credential = ServicePrincipalCredentials(tenant=tenant_id, client_id=client_id, secret=client_secret)
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
在此方法中(再次用于非基于 azure.core 的旧库),将使用从安全存储(例如 Azure Key Vault 或环境变量)中获取的凭据创建 ServicePrincipalCredentials 对象。In this method, which is again used with older libraries not based on azure.core, you create a ServicePrincipalCredentials object using credentials obtained from secure storage such as Azure Key Vault or environment variables. 前面的代码假定已创建配置本地开发环境中所述的环境变量。The previous code assumes that you've created the environment variables described in Configure your local dev environment.
使用 Azure 主权国家云Use an Azure sovereign national cloud
使用这些令牌凭据方法的其中一个,可以通过为客户端对象指定 base_url 参数来使用 Azure 主权或国家云,而不是 Azure 公有云:With either of these token credential methodsthis method, you can use an Azure sovereign or national cloud rather than the Azure public cloud by specifying a base_url argument for the client object:
from msrestazure.azure_cloud import AZURE_CHINA_CLOUD
#...
subscription_client = SubscriptionClient(credentials, base_url=AZURE_CHINA_CLOUD.endpoints.resource_manager)
使用令牌凭据和 ADAL 上下文进行身份验证Authenticate with token credentials and an ADAL context
If you need more control when using token credentials, use the Azure Active Directory Authentication Library (ADAL) for Python and the SDK ADAL wrapper:
import os, adal
from azure.mgmt.resource import SubscriptionClient
from msrestazure.azure_active_directory import AdalAuthentication
from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD
# Retrieve the IDs and secret to use with ServicePrincipalCredentials
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
tenant_id = os.environ["AZURE_TENANT_ID"]
client_id = os.environ["AZURE_CLIENT_ID"]
client_secret = os.environ["AZURE_CLIENT_SECRET"]
LOGIN_ENDPOINT = AZURE_PUBLIC_CLOUD.endpoints.active_directory
RESOURCE = AZURE_PUBLIC_CLOUD.endpoints.active_directory_resource_id
context = adal.AuthenticationContext(LOGIN_ENDPOINT + '/' + tenant_id)
credential = AdalAuthentication(context.acquire_token_with_client_credentials,
RESOURCE, client_id, client_secret)
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
如果需要 ADAL 库,请运行 pip install adal。If you need the ADAL library, run pip install adal.
使用此方法,可以使用 Azure 主权或国家云,而不是 Azure 公有云。With this method, you can use an Azure sovereign or national cloud rather than the Azure public cloud.
from msrestazure.azure_cloud import AZURE_CHINA_CLOUD
# ...
LOGIN_ENDPOINT = AZURE_CHINA_CLOUD.endpoints.active_directory
RESOURCE = AZURE_CHINA_CLOUD.endpoints.active_directory_resource_id
只需将 AZURE_PUBLIC_CLOUD 替换为 msrestazure.azure_cloud 库中的相应主权云常量。Simply replace AZURE_PUBLIC_CLOUD with the appropriate sovereign cloud constant from the msrestazure.azure_cloud library.
基于 CLI 的身份验证(仅限开发目的)CLI-based authentication (development purposes only)
在此方法中,将使用通过 Azure CLI 命令 az login 登录的用户的凭据创建客户端对象。In this method, you create a client object using the credentials of the user signed in with the Azure CLI command az login. 基于 CLI 的身份验证仅适用于开发目的,因为无法在生产环境中使用它。CLI-based authentication works only for development purposes because it cannot be used in production environments.
Azure 库默认的订阅 ID,你也可使用 az account 在运行代码之前设置订阅。The Azure libraries use the default subscription ID, or you can set the subscription prior to running the code using az account.
使用基于 CLI 的身份验证时,会针对 CLI 登录凭据允许的所有操作向应用程序授权。When using CLI-based authentication, the application is authorized for any and all operations allowed by the CLI login credentials. 结果是,如果你是订阅的所有者或管理员,那么无需分配任何特定权限,你的代码就可访问该订阅中的大多数资源。As a result, if you are the owner or administrator of your subscription, your code has inherent access to most resources in that subscription without having to assign any specific permissions. 此行为对于试验非常方便。This behavior is convenient for experimentation. 但是,强烈建议你在开始编写生产代码时使用特定服务主体并分配特定权限,因为你会了解如何将确切的权限分配给不同的标识,而且在部署到生产环境之前,可在测试环境中准确验证这些权限。However, we highly recommend that you use specific service principals and assign specific permissions when you start writing production code because you learn how to assign exact permissions to different identities and can accurately validate those permissions in test environments before deploying to production.
使用 azure.core 库的基于 CLI 的身份验证CLI-based authentication with azure.core libraries
When using Azure libraries that are updated for azure.core, use the the AzureCliCredential object from the azure-identity library (version 1.4.0+). 例如,可将以下代码用于 azure-mgmt-resource 版本 15.0.0+:For example, the following code can be used with azure-mgmt-resource versions 15.0.0+:
from azure.identity import AzureCliCredential
from azure.mgmt.resource import SubscriptionClient
credential = AzureCliCredential()
subscription_client = SubscriptionClient(credential)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
使用更旧的(非 azure.core)库的基于 CLI 的身份验证CLI-based authentication with older (non azure.core) libraries
使用未针对 azure.core 更新的更旧的 Azure 库时,可使用 azure-cli-core 库中的 get_client_from_cli_profile 方法。When using older Azure libraries that have not been updated for azure.core, you can use the get_client_from_cli_profile method from the azure-cli-core library. 例如,可将以下代码用于版本低于 15.0.0 的 azure-mgmt-resource:For example, the following code can be used with versions of azure-mgmt-resource below 15.0.0:
from azure.common.client_factory import get_client_from_cli_profile
from azure.mgmt.resource import SubscriptionClient
subscription_client = get_client_from_cli_profile(SubscriptionClient)
subscription = next(subscription_client.subscriptions.list())
print(subscription.subscription_id)
If you need to refer to different subscriptions in the same script, then use the 'get_client_from_auth_file' or get_client_from_json_dict methods described earlier in this article.
不推荐使用:使用 UserPassCredentials 进行身份验证Deprecated: Authenticate with UserPassCredentials
此类不支持双因素身份验证,不应再使用。This class doesn't support two-factor authentication and should no longer be used.
另请参阅See also