当前位置: 首页 > 知识库问答 >
问题:

无法在Azure中使用系统分配托管标识使用Blob存储操作

苏鹏鹍
2023-03-14

获取"服务器验证请求失败。请确保包括签名在内的授权标头的值正确形成。"使用C#语言在Azure中尝试使用系统分配托管标识时出错。

接下来是步骤

  • 创建了一个启用标识(系统分配)的新VM
  • 使用存储帐户中的角色分配在IAM中添加虚拟机
  • 能够使用C#
  • 但在阅读blob时遇到异常,下面是异常的详细信息
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
   at Microsoft.Azure.Storage.Core.Executor.Executor.<ExecuteAsync>d__1`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Azure.Storage.Blob.CloudBlockBlob.<DownloadTextAsync>d__72.MoveNext()

课程

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var blob = new AzureCloudBlob();
                Console.WriteLine(blob.ReadBlob());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
        }
    }

AzureCloudBlob类,用于使用系统分配的托管Idenitity访问令牌连接和读取blob

    class AzureCloudBlob
    {
        public CloudBlockBlob CreateConnection()
        {
            var token = GetToken();
            var tokenCredentials = new TokenCredential(token);
            var storageCredentials = new StorageCredentials(tokenCredentials);
            var serviceUri = new Uri("https://mystorageacc.blob.core.windows.net/practice/blob.txt");

            return new CloudBlockBlob(serviceUri, storageCredentials);
        }

        public string ReadBlob()
        {
            var client = CreateConnection();
            var blobClient = client.DownloadTextAsync();
            var data = blobClient.Result;
            return data;
        }

        public string GetToken()
        {
            var request = (HttpWebRequest)WebRequest.Create("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/");
            request.Headers["Metadata"] = "true";
            request.Method = "GET";

            try
            {
                var response = (HttpWebResponse)request.GetResponse();
                var streamResponse = new StreamReader(response.GetResponseStream());
                string stringResponse = streamResponse.ReadToEnd();
                var list = (Dictionary<string, string>)JsonConvert.DeserializeObject(stringResponse, typeof(Dictionary<string, string>));
                string accessToken = list["access_token"];
                Console.WriteLine(accessToken);
                return accessToken;
            }
            catch (Exception e)
            {
                string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
                Console.WriteLine(errorText);
                return errorText;
            }
        }
    }

共有1个答案

颜嘉福
2023-03-14

如果您想使用Azure AD auth访问Azure存储,我们应该使用resource=https://storage.azure.com/获取Azure广告访问令牌。但是你使用资源=https://management.azure.com/。请把它换掉。此外,请注意,您需要为MSI分配正确的角色。该角色应该是存储Blob数据读取器、存储Blob数据参与者或存储Blob数据所有者。

具体步骤如下

>

  • 在Azure VM上启用系统分配的托管标识

    $vm = Get-AzVM -ResourceGroupName myResourceGroup -Name myVM
    Update-AzVM -ResourceGroupName myResourceGroup -VM $vm -AssignIdentity:$SystemAssigned
    

    在存储帐户作用域上将角色分配给MSI

    $sp =Get-AzADServicePrincipal -displayname "<your VM name>"
    New-AzRoleAssignment -ObjectId $sp.id `
        -RoleDefinitionName "Storage Blob Data Reader" `
        -Scope  "/subscriptions/<subscription>/resourceGroups/sample-resource-group/providers/Microsoft.Storage/storageAccounts/<storage-account>"
    

    密码

    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;
            }
        }
    }
    

  •  类似资料:
    • 在v11SDK. NET中,我能够使用托管标识令牌来访问Azure blob: 现在我想切换到v12 SDK,但不知道如何对BlobServiceClient进行同样的操作。

    • 接下来的步骤是: 创建了启用标识的新虚拟机(已分配系统) 使用存储帐户中的角色分配在IAM中添加虚拟机 能够使用C#生成令牌 为现有VM获取托管标识服务。 使用-az keyvault set-policy--name“”--object-id“--secret-permissions get list分配了访问azure KV的权限 现在,在执行来自VM的代码时,我得到一个错误

    • 我正在尝试使用托管标识从Azure Windows VM访问Azure存储资源。 我已经按照这里的指示做了https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-vm-windows-access-storage但本教程中的访问部分是使用完成的。NET,这

    • 我正在学习本教程,其中要求使用分配给Azure存储帐户的Azure托管标识。https://docs.microsoft.com/en-us/azure/storage/common/customer-managed-keys-overview#about-客户管理的密钥 在本教程中,请参见步骤1。是: Azure Key Vault管理员向与存储帐户关联的托管标识授予加密密钥权限 但是,我找不到

    • 有没有办法将Azure托管标识与LinuxVM一起使用来访问AzureSQL数据库?我只能找到这个文档https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-sql它专门针对Windows VM。Linux机器是否有文档

    • 当我试图使用分配了托管标识的系统在Azure Function应用程序中调用Azure函数以从Azure存储容器中获取blob时,我遇到了: