教程:使用 Windows VM/VMSS 访问 Azure 资源

Azure 资源的托管标识是 Microsoft Entra ID 的一项功能。 支持 Azure 资源的托管标识的每个 Azure 服务都受其自己的时间线限制。 在开始之前,请务必查看资源的托管标识的可用性状态以及已知问题

先决条件

使用 Windows VM 系统分配的托管标识访问 Azure 存储

本教程介绍了如何使用 Windows 虚拟机 (VM) 的系统分配的托管标识来访问 Azure 存储。 你将学习如何:

  • 在存储帐户中创建 Blob 容器
  • 向 Windows VM 的系统分配的托管标识授予对存储帐户的访问权限
  • 获取访问令牌并使用它来调用 Azure 存储

启用

启用系统分配的托管标识只需单击一次即可。 可以在创建 VM 的过程中或在现有 VM 的属性中启用它。

屏幕截图显示虚拟机的“系统分配”选项卡,可以在其中打开“系统分配”状态。

若要在新 VM 上启用系统分配的托管标识,请执行以下操作:

  1. 登录到 Azure 门户

  2. 创建启用了系统分配标识的虚拟机

创建存储帐户

在本部分中,创建一个存储帐户。

  1. 选择 Azure 门户左上角的“+ 创建资源”按钮。

  2. 单击“存储”,然后单击“存储帐户 - Blob、文件、表、队列”。

  3. 在“名称”字段中,输入存储帐户的名称。

  4. “部署模型”和“帐户类型”应分别设置为“资源管理器”和“存储(常规用途 v1)”。

  5. 确保“订阅”和“资源组”与上一步中创建 VM 时指定的名称匹配。

  6. 选择创建

    屏幕截图显示如何新建存储帐户。

创建 blob 容器,并将文件上传到存储帐户

文件需要 blob 存储,因此你需要创建用于存储文件的 blob 容器。 然后将文件上传到新存储帐户中的 blob 容器。

  1. 导航到新创建的存储帐户。

  2. 在“Blob 服务”部分中,选择“容器”。

  3. 选择页面顶部的“+ 容器”。

  4. 在“新建容器”字段中,为容器输入一个名称,然后在“公共访问级别”选项中保留默认值。

    屏幕截图显示如何创建存储容器。

  5. 使用你选择的编辑器,在本地计算机上创建一个标题为 hello world.txt 的文件。 打开该文件并添加文本“Hello world!”,然后保存它。

  6. 要将文件上传到新创建的容器,请选择该容器名称,然后选择“上传”。

  7. 在“上传 Blob”窗格的“文件”部分中,选择文件夹图标并浏览到本地计算机上的文件 hello_world.txt。 然后,选择该文件并选择“上传”。 屏幕截图显示文本文件上传屏幕。

授予访问权限

本部分介绍如何授予 VM 访问 Azure 存储容器的权限。 可以使用 VM 的系统分配的托管标识检索 Azure 存储 blob 中的数据。

  1. 导航到新创建的存储帐户。

  2. 选择“访问控制 (IAM)”。

  3. 选择“添加”>“添加角色分配”,打开“添加角色分配”页面。

  4. 分配以下角色。 有关详细步骤,请参阅使用 Azure 门户分配 Azure 角色

    设置
    角色 存储 Blob 数据读取者
    将访问权限分配到 托管标识
    系统分配 虚拟机
    Select <你的虚拟机>

    用于添加角色分配的页面的屏幕截图。

访问数据

Azure 存储原生支持 Microsoft Entra 身份验证,因此可以直接接受使用托管标识获取的访问令牌。 此方法将 Azure 存储与 Microsoft Entra ID 集成结合使用,不同于在连接字符串中提供凭据。

以下 .NET 代码的示例是关于打开与 Azure 存储的连接。 该示例使用访问令牌,然后读取前面创建的文件的内容。 此代码必须在 VM 上运行才能访问 VM 的托管标识终结点。 使用访问令牌方法需要 .NET Framework 4.6 或更高版本。 相应地替换 <URI to blob file> 的值。 可以通过以下方式获取此值:在“概述”页上的“属性”下,导航到你创建并上传到 blob 存储的文件,然后复制 URL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Web.Script.Serialization;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

namespace StorageOAuthToken
{
    class Program
    {
        static void Main(string[] args)
        {
            //get token
            string accessToken = GetMSIToken("https://storage.azure.com/");

            //create token credential
            TokenCredential tokenCredential = new TokenCredential(accessToken);

            //create storage credentials
            StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);

            Uri blobAddress = new Uri("<URI to blob file>");

            //create block blob using storage credentials
            CloudBlockBlob blob = new CloudBlockBlob(blobAddress, storageCredentials);

            //retrieve blob contents
            Console.WriteLine(blob.DownloadText());
            Console.ReadLine();
        }

        static string GetMSIToken(string resourceID)
        {
            string accessToken = string.Empty;
            // Build request to acquire MSI token
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=" + resourceID);
            request.Headers["Metadata"] = "true";
            request.Method = "GET";

            try
            {
                // Call /token endpoint
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                // Pipe response Stream to a StreamReader, and extract access token
                StreamReader streamResponse = new StreamReader(response.GetResponseStream());
                string stringResponse = streamResponse.ReadToEnd();
                JavaScriptSerializer j = new JavaScriptSerializer();
                Dictionary<string, string> list = (Dictionary<string, string>)j.Deserialize(stringResponse, typeof(Dictionary<string, string>));
                accessToken = list["access_token"];
                return accessToken;
            }
            catch (Exception e)
            {
                string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
                return accessToken;
            }
        }
    }
}

响应包含文件内容:

Hello world! :)

禁用

若要在 VM 上禁用系统分配的标识,请将系统分配的标识的状态设为“关”。

屏幕截图显示虚拟机的“系统分配”选项卡,可以在其中关闭“系统分配”状态。

使用 Windows VM 系统分配的托管标识通过 SAS 凭据访问 Azure 存储

本教程介绍了如何使用系统分配的标识为 Windows 虚拟机 (VM) 获取存储共享访问签名 (SAS) 凭据。

服务 SAS 能够为特定的服务(在本例中是一个 blob 服务)授予在有限时间内访问存储帐户中对象的权限。 SAS 在不公开帐户访问密钥的情况下执行此操作。 你可以像往常一样使用 SAS 凭据执行存储操作;例如,当使用存储 SDK 时。 本教程展示了使用 Azure 存储 PowerShell 来上传和下载 blob。

将了解如何执行以下操作:

  • 创建存储帐户
  • 向 VM 授予对资源管理器中的存储帐户 SAS 的访问权限
  • 使用 VM 的标识获取一个访问令牌,并使用它从资源管理器检索 SAS

注意

建议使用 Azure Az PowerShell 模块与 Azure 交互。 请参阅安装 Azure PowerShell 以开始使用。 若要了解如何迁移到 Az PowerShell 模块,请参阅 将 Azure PowerShell 从 AzureRM 迁移到 Az

创建存储帐户

如果你还没有存储帐户,则需要创建一个。 否则,请按照这些步骤向 VM 的系统分配托管标识授予对现有存储帐户 SAS 凭据的访问权限。

  1. 选择“存储”,然后选择“存储帐户”。

  2. 在“创建存储帐户”面板中,为存储帐户输入一个名称。

  3. 请确保将“部署模型”和“帐户类型”分别设置为“资源管理器”和“常规用途”。

  4. 进行检查,以确保“订阅”和“资源组”与上一步中创建 VM 时指定的项匹配。

  5. 选择“创建”以创建你的存储帐户。

    屏幕截图显示如何创建新存储帐户。

在存储帐户中创建 Blob 容器

在本教程中,稍后你会将文件上传和下载到新存储帐户。 由于文件需要 blob 存储,因此你需要创建 blob 容器来存储它们。

  1. 导航到新创建的存储帐户。

  2. 在左侧面板中,选择“Blob 服务”下的“容器”链接。

  3. 选择页面顶部的“+ 容器”,此时应会显示“新建容器”面板。

  4. 为容器指定名称,确定访问级别,然后选择“确定”。 本教程的后面部分将使用你在此处指定的名称。

    屏幕截图显示如何创建存储容器。

授权 VM 的系统分配的托管标识使用存储 SAS

Azure 存储原本不支持 Microsoft Entra 身份验证。 但是,可以使用托管标识从资源管理器检索存储 SAS,然后使用 SAS 来访问存储。 在此步骤中,将向 VM 的系统分配的托管标识授予对存储帐户 SAS 的访问权限。

  1. 导航回新创建的存储帐户。

  2. 选择“访问控制 (IAM)”。

  3. 选择“添加”>“添加角色分配”,打开“添加角色分配”页面。

  4. 分配以下角色。 有关详细步骤,请参阅使用 Azure 门户分配 Azure 角色

    设置
    角色 存储帐户参与者
    将访问权限分配到 托管标识
    系统分配 虚拟机
    Select <你的 Windows 虚拟机>

    用于添加角色分配的页面的屏幕截图。

使用 VM 标识获取访问令牌,并使用它调用 Azure 资源管理器

在本教程的剩余部分中,你将从你的 VM 进行操作。 在此部分中,你需要使用 Azure 资源管理器 PowerShell cmdlet。 如果尚未安装 PowerShell,请下载最新版本,然后再继续。

  1. 在 Azure 门户中,导航到“虚拟机”,转到 Windows 虚拟机,然后在“概述”页中选择顶部的“连接”

  2. 输入你在创建 Windows VM 时添加的用户名和密码。

  3. 建立与虚拟机的远程桌面连接。

  4. 在远程会话中打开 PowerShell,然后使用 PowerShell Invoke-WebRequest cmdlet 从 Azure 资源终结点的本地托管标识获取 Azure 资源管理器令牌。

       $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.chinacloudapi.cn%2F' -Method GET -Headers @{Metadata="true"}
    

    注意

    resource 参数的值必须完全匹配 Microsoft Entra ID 预期的值。 如果使用 Azure 资源管理器资源 ID,必须在 URI 的结尾添加斜线。

    接下来,提取 content 元素,它以 JavaScript 对象表示法 (JSON) 格式字符串的形式存储在 $response 对象中。

    $content = $response.Content | ConvertFrom-Json
    

    接下来,从响应中提取访问令牌。

    $ArmToken = $content.access_token
    

从 Azure 资源管理器中获取 SAS 凭据,以便调用存储

最后,使用 PowerShell 使用在上一部分中检索到的访问令牌调用资源管理器。 你使用此令牌创建存储 SAS 凭据。 具有 SAS 凭据后,你可以调用其他存储操作。

对于此请求,请使用以下 HTTP 请求参数来创建 SAS 凭据:

{
    "canonicalizedResource":"/blob/<STORAGE ACCOUNT NAME>/<CONTAINER NAME>",
    "signedResource":"c",              // The kind of resource accessible with the SAS, in this case a container (c).
    "signedPermission":"rcw",          // Permissions for this SAS, in this case (r)ead, (c)reate, and (w)rite. Order is important.
    "signedProtocol":"https",          // Require the SAS be used on https protocol.
    "signedExpiry":"<EXPIRATION TIME>" // UTC expiration time for SAS in ISO 8601 format, for example 2017-09-22T00:06:00Z.
}

此处的参数包括在针对 SAS 凭据的请求的 POST 正文中。 有关用于创建 SAS 凭据的参数的详细信息,请参阅列出服务 SAS REST 参考

  1. 将参数转换为 JSON,然后调用存储 listServiceSas 终结点来创建 SAS 凭据:

    $params = @{canonicalizedResource="/blob/<STORAGE-ACCOUNT-NAME>/<CONTAINER-NAME>";signedResource="c";signedPermission="rcw";signedProtocol="https";signedExpiry="2017-09-23T00:00:00Z"}
    $jsonParams = $params | ConvertTo-Json
    
    $sasResponse = Invoke-WebRequest -Uri https://management.chinacloudapi.cn/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>/providers/Microsoft.Storage/storageAccounts/<STORAGE-ACCOUNT-NAME>/listServiceSas/?api-version=2017-06-01 -Method POST -Body $jsonParams -Headers @{Authorization="Bearer $ArmToken"}
    

    注意

    URL 区分大小写。因此,请确保使用的大小写与为资源组命名时使用的大小写完全相同,包括 resourceGroups 中的大写“G”。

  2. 接下来,从响应中提取 SAS 凭据:

    $sasContent = $sasResponse.Content | ConvertFrom-Json
    $sasCred = $sasContent.serviceSasToken
    
  3. 如果你检查 SAS 凭据,则会看到类似以下内容的内容:

    PS C:\> $sasCred
    sv=2015-04-05&sr=c&spr=https&se=2017-09-23T00%3A00%3A00Z&sp=rcw&sig=JVhIWG48nmxqhTIuN0uiFBppdzhwHdehdYan1W%2F4O0E%3D
    
  4. 创建一个名为“test.txt”的文件。 然后,通过 New-AzStorageContent cmdlet 使用 SAS 凭据进行身份验证,将该文件上传到 blob 容器,然后下载该文件。

    echo "This is a test text file." > test.txt
    
  5. 请务必首先使用 Install-Module Azure.Storage 安装 Azure 存储 cmdlet。 然后,使用 PowerShell Set-AzStorageBlobContent cmdlet 上传你刚才创建的 blob:

    $ctx = New-AzStorageContext -StorageAccountName <STORAGE-ACCOUNT-NAME> -SasToken $sasCred
    Set-AzStorageBlobContent -File test.txt -Container <CONTAINER-NAME> -Blob testblob -Context $ctx
    

    响应:

    ICloudBlob        : Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob
    BlobType          : BlockBlob
    Length            : 56
    ContentType       : application/octet-stream
    LastModified      : 9/21/2017 6:14:25 PM +00:00
    SnapshotTime      :
    ContinuationToken :
    Context           : Microsoft.WindowsAzure.Commands.Storage.AzureStorageContext
    Name              : testblob
    
  6. 也可以使用 Get-AzStorageBlobContent PowerShell cmdlet 下载刚上传的 blob:

    Get-AzStorageBlobContent -Blob testblob -Container <CONTAINER-NAME> -Destination test2.txt -Context $ctx
    

    响应:

    ICloudBlob        : Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob
    BlobType          : BlockBlob
    Length            : 56
    ContentType       : application/octet-stream
    LastModified      : 9/21/2017 6:14:25 PM +00:00
    SnapshotTime      :
    ContinuationToken :
    Context           : Microsoft.WindowsAzure.Commands.Storage.AzureStorageContext
    Name              : testblob
    

使用 Windows VM 系统分配托管标识访问 Azure SQL 数据库

本教程介绍如何使用 Windows 虚拟机 (VM) 的系统分配标识访问 Azure SQL 数据库。 托管服务标识由 Azure 自动管理,可用于向支持 Microsoft Entra 身份验证的服务进行身份验证,这样就无需在代码中插入凭据了。

将了解如何执行以下操作:

  • 授予 VM 对 Azure SQL 数据库的访问权限
  • 启用 Microsoft Entra 身份验证
  • 在数据库中创建一个代表 VM 的系统分配标识的包含用户
  • 使用 VM 标识获取访问令牌,并使用它查询 Azure SQL 数据库

启用

启用系统分配的托管标识只需单击一次即可。 可以在创建 VM 的过程中或在现有 VM 的属性中启用它。

屏幕截图显示虚拟机的“系统分配”选项卡,可以在其中打开“系统分配”状态。

若要在新 VM 上启用系统分配的托管标识,请执行以下操作:

  1. 登录到 Azure 门户

  2. 创建启用了系统分配标识的虚拟机

授予访问权限

若要授予 VM 对 Azure SQL 数据库中数据库的访问权限,请使用现有逻辑 SQL Server 或创建新的 SQL Server。 若要使用 Azure 门户创建新的服务器和数据库,请遵循此 Azure SQL 快速入门Azure SQL 文档中还提供了有关使用 Azure CLI 和 Azure PowerShell 执行这些操作的快速入门。

按照以下步骤授予 VM 对数据库的访问权限:

  1. 为服务器启用 Microsoft Entra 身份验证。
  2. 在数据库中创建一个代表 VM 的系统分配标识的包含用户

启用 Microsoft Entra 身份验证

若要配置 Microsoft Entra 身份验证,请执行以下操作:

  1. 在 Azure 门户中,从左侧导航栏中选择“SQL Server”。
  2. 选择你要启用 Microsoft Entra 身份验证的 SQL Server。
  3. 在边栏选项卡的“设置”部分中,选择“Active Directory 管理员”。
  4. 在命令栏中,选择“设置管理员”。
  5. 选择要设为服务器管理员的 Microsoft Entra 用户帐户,然后选择“选择”。
  6. 在命令栏中,选择“保存”。

创建包含用户

本部分介绍了如何在数据库中创建一个表示 VM 的系统分配标识的包含用户。 要执行此步骤,你需要安装 Microsoft SQL Server Management Studio (SSMS)。 在开始之前,查看以下文章来了解有关 Microsoft Entra 集成的背景知识可能很有帮助:

SQL 数据库需要唯一的 Microsoft Entra ID 显示名称。 因此,Microsoft Entra 帐户(例如用户、组和服务主体(应用程序))以及启用了托管标识的 VM 名称必须在特定于其相应显示名称的 Microsoft Entra ID 中是唯一定义的。 在通过 T-SQL 创建此类用户期间,SQL 会检查 Microsoft Entra ID 显示名称。 如果显示名称不唯一,则命令将失败,并提示你为每个给定帐户提供唯一的 Microsoft Entra ID 显示名称。

创建包含的用户

  1. 打开 SQL Server Management Studio。

  2. 在“连接到服务器”对话框的“服务器名称”字段中,输入服务器名称。

  3. 在“身份验证”字段中,选择“Active Directory - 通用且具有 MFA 支持”。

  4. 在“用户名”字段中,输入已设为服务器管理员的 Microsoft Entra 帐户的名称,例如 cjensen@fabrikam.com

  5. 选择“选项”。

  6. 在“连接到数据库”字段中,输入要配置的非系统数据库的名称。

  7. 选择“连接”,然后完成登录过程。

  8. 在“对象资源管理器”中,展开“数据库”文件夹。

  9. 右键单击用户数据库并选择“新建查询”。

  10. 在查询窗口中输入以下行,在工具栏中选择“执行”

    注意

    以下命令中的 VMName 是在“先决条件”部分中对其启用系统分配标识的 VM 的名称。

    CREATE USER [VMName] FROM EXTERNAL PROVIDER
    

    该命令应该会成功完成,为 VM 的系统分配标识创建包含的用户。

  11. 清除查询窗口,输入以下行,然后在工具栏中选择“执行”

    注意

    以下命令中的 VMName 是在“先决条件”部分中对其启用系统分配标识的 VM 的名称。

    如果遇到错误“主体 VMName 具有重复的显示名称”,请在 CREATE USER 语句后追加 WITH OBJECT_ID='xxx'。

    ALTER ROLE db_datareader ADD MEMBER [VMName]
    

    该命令应该会成功完成,并授予包含的用户读取整个数据库的权限。

VM 中运行的代码现在可使用其系统分配托管标识获取令牌,并使用该令牌在服务器中进行身份验证。

访问数据

本部分介绍了如何使用 VM 的系统分配托管标识获取访问令牌,并使用它调用 Azure SQL。 Azure SQL 原本就支持 Microsoft Entra 身份验证,因此可以直接接受使用 Azure 资源的托管标识获取的访问令牌。 此方法不需要在连接字符串上提供凭据。

下面是使用 Active Directory 托管标识身份验证打开 SQL 连接的 .NET 代码示例。 此代码必须在 VM 上运行才能访问 VM 系统分配的托管标识的终结点。

使用此方法需要 .NET Framework 4.6.2 或更高版本或者 .NET Core 3.1 或更高版本。 相应地替换 AZURE-SQL-SERVERNAME 和 DATABASE 的值,并添加对 Microsoft.Data.SqlClient 库的 NuGet 引用。

using Microsoft.Data.SqlClient;

try
{
//
// Open a connection to the server using Active Directory Managed Identity authentication.
//
string connectionString = "Data Source=<AZURE-SQL-SERVERNAME>; Initial Catalog=<DATABASE>; Authentication=Active Directory Managed Identity; Encrypt=True";
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();

注意

可以使用托管标识,同时使用 SDK 处理其他编程选项。

或者,使用 PowerShell 来测试端到端设置,而无需在 VM 上编写和部署应用。

  1. 在门户中,导航到“虚拟机”,转到你的 Windows VM,然后在“概述”中选择“连接”

  2. 输入你在创建 Windows VM 时添加的 VM 管理员凭据。

  3. 现在,你已经创建了与 VM 的远程桌面连接,请在远程会话中打开 PowerShell。

  4. 使用 PowerShell Invoke-WebRequest cmdlet 向本地托管标识的终结点发出请求,以获取 Azure SQL 的访问令牌。

        $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fdatabase.chinacloudapi.cn%2F' -Method GET -Headers @{Metadata="true"}
    

    将响应从 JSON 对象转换为 PowerShell 对象。

    $content = $response.Content | ConvertFrom-Json
    

    从响应中提取访问令牌。

    $AccessToken = $content.access_token
    
  5. 与服务器建立连接。 请记得替换 AZURE-SQL-SERVERNAME 和 DATABASE 的值。

    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Data Source = <AZURE-SQL-SERVERNAME>; Initial Catalog = <DATABASE>; Encrypt=True;"
    $SqlConnection.AccessToken = $AccessToken
    $SqlConnection.Open()
    

    接下来,创建一个查询并将其发送到服务器。 请记得替换 TABLE 的值。

    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = "SELECT * from <TABLE>;"
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    

最后,检查 $DataSet.Tables[0] 的值,以查看查询结果。

禁用

若要在 VM 上禁用系统分配的标识,请将系统分配的标识的状态设为“关”。

屏幕截图显示虚拟机的“系统分配”选项卡,可以在其中关闭“系统分配”状态。

使用 Windows VM 系统分配的托管标识访问 Azure Key Vault

本教程介绍 Windows 虚拟机 (VM) 如何使用系统分配的托管标识来访问 Azure Key Vault。 Key Vault 使客户端应用程序能够使用机密来访问不受 Microsoft Entra ID 保护的资源。 托管标识由 Azure 自动管理。 它们使你可以向支持 Microsoft Entra 身份验证的服务进行身份验证,而无需在代码中加入身份验证信息。

将了解如何执行以下操作:

  • 授予 VM 对 Key Vault 中存储的密钥的访问权限
  • 使用 VM 标识获取访问令牌,并使用它来检索 Key Vault 中的密钥

创建密钥保管库

提示

本文中的步骤可能因开始使用的门户而略有不同。

本部分说明如何授予 VM 访问密钥保管库中存储的密钥的权限。 使用 Azure 资源托管标识时,代码可以获取访问令牌,以向支持 Microsoft Entra 身份验证的资源进行身份验证。

但是,并非所有 Azure 服务都支持 Microsoft Entra 身份验证。 若要将 Azure 资源的托管标识用于这些服务,请将服务凭据存储在 Azure Key Vault 中,然后使用 VM 的托管标识访问 Key Vault 以检索凭据。

首先,你需要创建一个 Key Vault 并授予 VM 的系统分配托管标识对该 Key Vault 的访问权限。

  1. 登录到 Azure 门户

  2. 在左侧导航栏的顶部,选择“创建资源”

  3. 在“搜索市场”框中,键入“Key Vault”,然后按 Enter

  4. 从结果中选择“Key Vault”,然后选择“创建”

  5. 为新密钥保管库提供一个“名称”

    “创建 Key Vault”屏幕的屏幕截图。

  6. 填写所有必要信息。 请确保选择用于本教程的订阅和资源组。

  7. 选择“查看 + 创建”。

  8. 选择创建

创建机密

接下来,你需要将机密添加到 Key Vault,以便稍后可以使用在 VM 中运行的代码检索此机密。 在本部分中,你将使用 PowerShell,但相同的概念适用于你在 VM 中执行的任何代码。

  1. 导航到新创建的密钥保管库。

  2. 选择“机密”,然后选择“添加”。

  3. 选择生成/导入

  4. 在“创建密钥”屏幕的“上传选项”中,将“手动”保留为选中状态

  5. 输入密钥的名称和值。 该值可以是任何需要的内容。 

  6. 明确指定激活日期和到期日期,并将“已启用”设置为“是”。 

  7. 选择“创建”以创建机密。

    屏幕截图显示如何创建机密。

授予访问权限

需要向 VM 使用的托管标识授予访问权限,以便读取存储在该 Key Vault 中的密钥。

  1. 导航到新创建的密钥保管库。

  2. 在左侧菜单中选择“访问策略”。

  3. 选择“添加访问策略”。

    屏幕截图显示“密钥保管库访问策略”屏幕。

  4. 在“从模板配置(可选)”下的“添加访问策略”部分的下拉菜单中选择“密钥管理”

  5. 选择“选择主体”,然后在搜索字段中输入你之前创建的 VM 的名称。 

  6. 在结果列表中选择该 VM,然后选择“选择”。

  7. 选择“添加”。

  8. 选择“保存”。

访问数据

本部分介绍了如何使用 VM 标识获取访问令牌并使用它从密钥保管库中检索机密。 如果未安装 PowerShell 4.3.1 或更高版本,则需要下载并安装最新版本

注意

在特别需要使用托管标识的情况下,或者将流程嵌入在应用程序代码中时,首选使用 PowerShell 进行身份验证和检索机密。

首先,使用 VM 的系统分配托管标识获取访问令牌,向 Key Vault 证明身份:

  1. 在门户中,导航到“虚拟机”,转到你的 Windows VM,然后在“概述”中选择“连接”
  2. 输入你在创建 Windows VM 时添加的用户名和密码。
  3. 现在,你已经创建了与 VM 的远程桌面连接,请在远程会话中打开 PowerShell。
  4. 在 PowerShell 中,调用租户上的 Web 请求,为 VM 特定端口中的本地主机获取令牌。

注意

如果使用的是主权云(例如 GCC-H),请在 PowerShell cmdlet 中使用终结点 vault.usgovcloudapi.net 而非 vault.azure.cn

PowerShell 请求示例:

$Response = Invoke-RestMethod -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.cn' -Method GET -Headers @{Metadata="true"} 

注意

使用主权云时,你需要调整在 cmdlet 末尾指定的终结点。

例如,使用 Azure 政府云时应使用 vault.usgovcloudapi.net,并且最终结果如下:

$Response = Invoke-RestMethod -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.usgovcloudapi.net' -Method GET -Headers @{Metadata="true"

若要确认后缀是否与你的环境匹配,请查看 Azure Key Vault 安全性概述一文。

响应应如下所示:

屏幕截图显示带有令牌响应的请求。

接下来,从响应中提取访问令牌。

   $KeyVaultToken = $Response.access_token

最后,使用 PowerShell Invoke-WebRequest cmdlet 检索你之前在 Key Vault 中创建的密钥,并在授权标头中传递访问令牌。 将需要 Key Vault 的 URL,该 URL 位于 Key Vault 的“概述”页的“Essentials”部分。

Invoke-RestMethod -Uri https://<your-key-vault-URL>/secrets/<secret-name>?api-version=2016-10-01 -Method GET -Headers @{Authorization="Bearer $KeyVaultToken"}

响应应为如下所示:

  value       id                                                                                    attributes
  -----       --                                                                                    ----------
  'My Secret' https://mi-lab-vault.vault.azure.cn/secrets/mi-test/50644e90b13249b584c44b9f712f2e51 @{enabled=True; created=16…

在检索 Key Vault 中的密钥后,可以使用该密钥对需要名称和密码的服务进行身份验证。

清理资源

最后,当你需要清理资源时,请登录到 Azure 门户,选择“资源组”,找到并选择在本教程中创建的资源组(例如 mi-test)。 然后,使用“删除资源组”命令。

或者,还可以使用 PowerShell 或 CLI 来清理资源。

使用 Windows VM 系统分配的托管标识访问资源管理器

提示

本文中的步骤可能因开始使用的门户而略有不同。

本教程介绍了如何创建系统分配的标识、将其分配给 Windows 虚拟机 (VM),然后再使用该标识访问 Azure 资源管理器 API。 托管服务标识由 Azure 自动管理。 此标识可用于向支持 Microsoft Entra 身份验证的服务进行身份验证,这样就无需在代码中嵌入凭据了。

将了解如何执行以下操作:

  • 授予 VM 对 Azure 资源管理器的访问权限。
  • 使用 VM 的系统分配的托管标识获取访问令牌以访问资源管理器。
  1. 使用管理员帐户登录 Azure 门户

  2. 导航到“资源组”选项卡。

  3. 选择要向其授予 VM 的托管标识访问权限的“资源组”

  4. 在左侧面板中,选择“访问控制(IAM)”。

  5. 依次选择“添加”和“添加角色分配”。

  6. 在“角色”选项卡中,选择“读取者”。 使用此角色可以查看所有资源,但不能进行任何更改。

  7. 在“成员”选项卡中,对于“将访问权限分配给”选项,选择“托管标识”,然后选择“+ 选择成员”。

  8. 确保“订阅”下拉列表中列出的订阅正确无误。 对于“资源组”,请选择“所有资源组”

  9. 在“管理标识”下拉列表中选择“虚拟机”。

  10. 对于“选择”,请选择下拉列表中的 VM 并选择“保存”

    屏幕截图显示了向托管标识添加读取者角色。

获取访问令牌

使用 VM 的系统分配的托管标识并调用资源管理器以获取访问令牌。

若要完成这些步骤,需要使用 SSH 客户端。 如果使用的是 Windows,可以在适用于 Linux 的 Windows 子系统中使用 SSH 客户端。 如果需要有关配置 SSH 客户端密钥的帮助,请参阅如何在 Azure 上将 SSH 密钥与 Windows 配合使用如何创建和使用适用于 Azure 中 Linux VM 的 SSH 公钥和私钥对

  1. 在门户中导航到 Linux VM,然后在“概述”中选择“连接”。
  2. 使用所选的 SSH 客户端连接到 VM。
  3. 在终端窗口中,使用 curl 向 Azure 资源终结点的本地托管标识发出请求,以获取 Azure 资源管理器的访问令牌。   下面是对访问令牌的 curl 请求。
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.chinacloudapi.cn/' -H Metadata:true

注意

resource 参数的值必须完全匹配 Microsoft Entra ID 预期的值。 若为资源管理器的资源 ID,必须在 URI 的结尾添加斜线。

响应包括访问 Azure 资源管理器所需的访问令牌。

响应:

{
  "access_token":"eyJ0eXAiOi...",
  "refresh_token":"",
  "expires_in":"3599",
  "expires_on":"1504130527",
  "not_before":"1504126627",
  "resource":"https://management.chinacloudapi.cn",
  "token_type":"Bearer"
}

请使用此访问令牌访问 Azure 资源管理器以实现特定目的,例如读取资源组(你之前向此 VM 授予了对它的访问权限)的详细信息。 将值 <SUBSCRIPTION-ID><RESOURCE-GROUP><ACCESS-TOKEN> 替换为之前创建的值。

注意

URL 区分大小写。因此,请确保大小写与之前在命名资源组时使用的大小写完全相同,并确保“resourceGroup”中使用的是大写“G”。

curl https://management.chinacloudapi.cn/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>?api-version=2016-09-01 -H "Authorization: Bearer <ACCESS-TOKEN>" 

返回的响应包含具体的资源组信息:

{
"id":"/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/DevTest",
"name":"DevTest",
"location":"chinanorth",
"properties":
{
  "provisioningState":"Succeeded"
  }
} 

使用 Windows VM 上用户分配的托管标识访问 Azure 资源管理器

本教程介绍了如何创建用户分配的标识、将其分配给 Windows 虚拟机 (VM),然后再使用该标识访问 Azure 资源管理器 API。 托管服务标识由 Azure 自动管理。 此标识可用于向支持 Microsoft Entra 身份验证的服务进行身份验证,这样就无需在代码中嵌入凭据了。

将了解如何执行以下操作:

  • 创建用户分配的托管标识
  • 将用户分配的标识分配给 Windows VM
  • 向用户分配的标识授予对 Azure 资源管理器中资源组的访问权限
  • 使用用户分配的标识获取访问令牌,并使用它调用 Azure 资源管理器
  • 读取资源组属性

注意

建议使用 Azure Az PowerShell 模块与 Azure 交互。 请参阅安装 Azure PowerShell 以开始使用。 若要了解如何迁移到 Az PowerShell 模块,请参阅 将 Azure PowerShell 从 AzureRM 迁移到 Az

在本地配置 Azure PowerShell

若要在本文情景中本地使用 Azure PowerShell,请完成以下步骤:

  1. 安装最新版本的 Azure PowerShell(如果尚未安装)。

  2. 登录 Azure:

    Connect-AzAccount -Environment AzureChinaCloud
    
  3. 安装最新版本的 PowerShellGet

    Install-Module -Name PowerShellGet -AllowPrerelease
    

    在下一步运行此命令后,可能需要 Exit 退出当前 PowerShell 会话。

  4. 安装 Az.ManagedServiceIdentity 模块的已发布版本。 你需要使用此模块来执行本教程中的用户分配托管标识操作:

    Install-Module -Name Az.ManagedServiceIdentity -AllowPrerelease
    

启用

对于基于用户分配的标识的场景,你需要在本部分中执行以下步骤:

  1. 创建标识。
  2. 分配新创建的标识。

创建标识

本部分介绍了如何创建用户分配的标识,该标识创建为独立的 Azure 资源。 借助 New-AzUserAssignedIdentity cmdlet,Azure 可在你的 Microsoft Entra 租户中创建可分配给一个或多个 Azure 服务实例的标识。

重要

创建用户分配的托管标识时,名称必须以字母或数字开头,并且可能包含字母数字字符、连字符 (-) 和下划线 (_) 的组合。 要使虚拟机或虚拟机规模集的分配正常工作,该名称限制为 24 个字符。 有关详细信息,请参阅 FAQ 和已知问题

New-AzUserAssignedIdentity -ResourceGroupName myResourceGroupVM -Name ID1

该响应包含已创建的用户分配标识的详细信息,与以下示例类似。 请为用户分配的标识定义 IdClientId 值,因为在后续步骤中将使用它们:

{
Id: /subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ID1
ResourceGroupName : myResourceGroupVM
Name: ID1
Location: chinanorth
TenantId: aaaabbbb-0000-cccc-1111-dddd2222eeee
PrincipalId: aaaaaaaa-bbbb-cccc-1111-222222222222
ClientId: 00001111-aaaa-2222-bbbb-3333cccc4444
ClientSecretUrl: https://control-chinanorth.identity.chinacloudapi.cn/subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ID1/credentials?tid=aaaabbbb-0000-cccc-1111-dddd2222eeee&oid=aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb&aid=00001111-aaaa-2222-bbbb-3333cccc4444
Type: Microsoft.ManagedIdentity/userAssignedIdentities
}

分配标识

本部分介绍了如何将用户分配的标识分配给 Windows VM。 用户分配的标识可以由多个 Azure 资源上的客户端使用。 使用以下命令将用户分配的标识分配给单个 VM。 将上一步返回的 Id 属性用于 -IdentityID 参数。

$vm = Get-AzVM -ResourceGroupName myResourceGroup -Name myVM
Update-AzVM -ResourceGroupName TestRG -VM $vm -IdentityType "UserAssigned" -IdentityID "/subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ID1"

授予访问权限

本部分介绍了如何授予用户分配的标识访问 Azure 资源管理器中的资源组的权限。 Azure 资源托管标识提供了相关标识,你的代码可使用这些标识来请求访问令牌,以向支持 Microsoft Entra 身份验证的资源 API 进行身份验证。 在本教程中,你的代码将访问 Azure 资源管理器 API。

需先向标识授予对 Azure 资源管理器中资源的访问权限,代码才能访问 API。 在此情况下,你将访问包含 VM 的资源组。 根据环境适当地更新 <SUBSCRIPTIONID> 的值。

$spID = (Get-AzUserAssignedIdentity -ResourceGroupName myResourceGroupVM -Name ID1).principalid
New-AzRoleAssignment -ObjectId $spID -RoleDefinitionName "Reader" -Scope "/subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM/"

响应包含所创建的角色分配的详细信息,与以下示例类似:

RoleAssignmentId: /subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM/providers/Microsoft.Authorization/roleAssignments/00000000-0000-0000-0000-000000000000
Scope: /subscriptions/<SUBSCRIPTIONID>/resourcegroups/myResourceGroupVM
DisplayName: ID1
SignInName:
RoleDefinitionName: Reader
RoleDefinitionId: 00000000-0000-0000-0000-000000000000
ObjectId: aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb
ObjectType: ServicePrincipal
CanDelegate: False

访问数据

提示

本文中的步骤可能因开始使用的门户而略有不同。

获取访问令牌

在本教程的剩余部分中,你将从先前创建的 VM 进行操作。

  1. 登录到 Azure 门户

  2. 在门户中,导航到“虚拟机”,然后转到 Windows VM。 在“概述”中选择“连接”。

  3. 输入你在创建 Windows VM 时使用的用户名和密码。

  4. 现在,你已经创建了与 VM 的远程桌面连接,请在远程会话中打开 PowerShell。

  5. 使用 Powershell Invoke-WebRequest cmdlet,向 Azure 资源终结点的本地托管标识发出请求以获取 Azure 资源管理器的访问令牌。 client_id 值是创建用户分配的托管标识时返回的值。

    $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&client_id=00001111-aaaa-2222-bbbb-3333cccc4444&resource=https://management.chinacloudapi.cn/' -Method GET -Headers @{Metadata="true"}
    $content = $response.Content | ConvertFrom-Json
    $ArmToken = $content.access_token
    

读取属性

最后,使用上一个步骤中检索到的访问令牌访问 Azure 资源管理器,然后读取向用户分配的标识授予了访问权限的资源组的属性。 将 <SUBSCRIPTION ID> 替换为你环境的订阅 ID。

(Invoke-WebRequest -Uri https://management.chinacloudapi.cn/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/myResourceGroupVM?api-version=2016-06-01 -Method GET -ContentType "application/json" -Headers @{Authorization ="Bearer $ArmToken"}).content

响应包含特定资源组信息,类似于下面的示例:

{"id":"/subscriptions/<SUBSCRIPTIONID>/resourceGroups/myResourceGroupVM","name":"myResourceGroupVM","location":"ChinaNorth","properties":{"provisioningState":"Succeeded"}}

了解详细信息