简体   繁体   English

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

[英]Not able to use blob storage operations using System Assigned Managed Identity in Azure

Getting "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."获取“服务器无法验证请求。确保授权 header 的值正确形成,包括签名。” error while trying to use System Assigned Managed Identity in Azure using C# language.尝试使用 C# 语言在 Azure 中使用系统分配的托管标识时出错。

The steps followed遵循的步骤

  • Created a new VM with Enabled Identity (System Assigned)使用已启用的标识(系统分配)创建了一个新 VM
  • Added the VM in IAM using Role Assignment in storage account使用存储帐户中的角色分配在 IAM 中添加了 VM
  • Able to generate token using C#能够使用 C# 生成令牌
  • But getting exception while reading blob, below are the exception details但是在读取 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()

The Program Class程序 Class

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

The AzureCloudBlob class, used to connect and read a blob using System Assigned Managed Idenitity access token AzureCloudBlob class,用于使用系统分配的托管身份访问令牌连接和读取 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;
            }
        }
    }

If you want to access Azure storage with Azure AD auth, we should use resouce=https://storage.azure.com/ to get Azure AD access token. If you want to access Azure storage with Azure AD auth, we should use resouce resouce=https://storage.azure.com/ to get Azure AD access token. But you use resource=https://management.azure.com/ .但是您使用resource=https://management.azure.com/ Please replace it.请更换它。 Besides, please note that you need to assign right role to the MSI.此外,请注意您需要为 MSI 分配正确的角色。 The role should be Storage Blob Data Reader , Storage Blob Data Contributor or Storage Blob Data Owner .角色应该是Storage Blob Data ReaderStorage Blob Data ContributorStorage Blob Data Owner

The detailed steps are as below详细步骤如下

  1. Enable system-assigned managed identity on Azure VM在 Azure VM 上启用系统分配的托管标识

    $vm = Get-AzVM -ResourceGroupName myResourceGroup -Name myVM Update-AzVM -ResourceGroupName myResourceGroup -VM $vm -AssignIdentity:$SystemAssigned
  2. Assign role to MSI on storage account scope将角色分配给存储帐户 scope 上的 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>"
  3. code代码

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

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法使用 Azure 中的系统分配的托管标识读取 Azure Key Vault 机密值 - Not able to read Azure Key Vault secret value using System Assigned Managed Identity in Azure 如何将 Azure 托管标识与 Azure.Storage.Blobs.BlobServiceClient 一起使用? - How to use Azure managed identity with Azure.Storage.Blobs.BlobServiceClient? 如何将 MSI(托管服务标识)与 Azure 存储模拟器一起使用? - How to use MSI(Managed Service Identity) with Azure storage emulator? Azure 存储帐户使用托管标识和 C# 进行身份验证 - Azure Storage Account authenticate using Managed Identity and C# "如何使用用户分配的托管标识访问 Azure 中 Function App Config 的 Key Vault" - How to use user-assigned managed identity to access Key Vault for Function App Config in Azure 允许应用服务仅由测试用户和使用系统分配的托管标识的另一个应用服务调用 - Allow App Service to be called by just a test user and another App Service using a system assigned managed identity Azure Function 函数如何使用托管标识获取对 Azure 表存储的引用? - How can an Azure Function function get a reference to Azure Table storage using Managed Identity? 具有用户分配的托管标识的 Azure 应用服务使应用程序崩溃 - Azure App Service with User-Assigned Managed Identity crashes application 对部署到 Azure 的应用程序使用 Azure 托管标识? - Using Azure Managed Identity for app deployed to Azure? 使用Https的Azure Blob存储 - Azure Blob Storage using Https
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM