C# Azure函数如何使用托管标识获取对Azure表存储的引用?

C# Azure函数如何使用托管标识获取对Azure表存储的引用?,c#,azure,azure-functions,azure-storage,azure-managed-identity,C#,Azure,Azure Functions,Azure Storage,Azure Managed Identity,我有一个Azure函数,该函数已被分配系统标识: 我希望Azure功能访问存储帐户。该函数在该存储帐户上具有读卡器和数据访问角色: 已使用要使用的存储帐户的名称配置该函数。然后,该函数尝试获取CloudTableClient的实例: public async Task InitAsync(string accountsStorageName) { var azureServiceTokenProvider = new AzureServiceTokenProvider();

我有一个Azure函数,该函数已被分配系统标识:

我希望Azure功能访问存储帐户。该函数在该存储帐户上具有
读卡器和数据访问
角色:

已使用要使用的存储帐户的名称配置该函数。然后,该函数尝试获取CloudTableClient的实例:

public async Task InitAsync(string accountsStorageName)
{
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(accountsStorageName);
    
    var storageCredential = new StorageCredentials(accessToken);
    var storageAccount = new CloudStorageAccount(storageCredential, accountsStorageName, "core.windows.net", true);
                
     //  Gets the client to the account's Table storage.
    m_tableClient = storageAccount.CreateCloudTableClient();
}
问题

由于无法获取访问令牌,上述代码失败:


Azure函数如何使用托管标识获取对Azure表存储的引用?

Azure密钥库可以生成共享访问签名令牌。共享访问签名提供对存储帐户中资源的委派访问。您可以授予客户端访问存储帐户中资源的权限,而无需共享帐户密钥。有关详细信息,请参阅

  • 设置帐户共享访问签名定义
  • 代码
  • 公共静态类Http
    {
    [函数名(“Http”)]
    公共静态异步任务运行(
    [HttpTrigger(AuthorizationLevel.Anonymous,“get”,“post”,Route=null)]HttpRequest请求,
    ILogger日志,ExecutionContext(上下文)
    {
    var azureServiceTokenProvider=新azureServiceTokenProvider();
    var kv=新的KeyVaultClient(新的KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    SecretBundle sasToken=wait kv.GetSecretAsync(secretIdentifier:https://testkey02.vault.azure.net:443/secrets/teststorage08-sasToken”);
    var storageCredential=新的StorageCredentials(sasToken.Value);
    var accountsStorageName=“teststorage08”;
    var storageAccount=新的CloudStorageAccount(storageCredential,accountsStorageName,“core.windows.net”,true);
    var tableClient=storageAccount.CreateCloudTableClient();
    var table=tableClient.GetTableReference(“客户”);
    wait table.CreateIfNotExistsAsync();
    CustomerEntity customer=新的CustomerEntity(“竖琴”、“沃尔特”)
    {
    电子邮件=”Walter@contoso.com",
    电话号码=“425-555-0101”
    };
    TableOperation insertOrMergeOperation=TableOperation.InsertOrMerge(客户);
    TableResult结果=等待table.ExecuteAsync(insertOrMergeOperation);
    CustomerEntity insertedCustomer=结果。结果为CustomerEntity;
    返回新的OkObjectResult(insertedCustomer);
    }       
    }
    公共类CustomerEntity:TableEntity
    {
    公共客户()
    {
    }
    公共CustomerEntity(字符串lastName、字符串firstName)
    {
    PartitionKey=lastName;
    RowKey=firstName;
    }
    公共字符串电子邮件{get;set;}
    公共字符串PhoneNumber{get;set;}
    }
    

    不支持表存储,另请参阅。正如您在角色中所看到的,blob、队列和文件只有rbac角色。@PeterBons在我的例子中,存储帐户是一个关键的vault管理存储帐户。那么,有没有办法通过密钥库访问存储帐户?我没有使用kv托管存储帐户的经验,但在我看来,您应该能够使用托管身份访问kv并创建SAS令牌:@Kzrystof您还有其他问题吗?如果你没有其他顾虑,你能接受它作为一个答案吗?
    $storageAccountName = ""
    $keyVaultName = ""
    $storageContext = New-AzStorageContext -StorageAccountName $storageAccountName -Protocol Https -StorageAccountKey Key1
    $start = [System.DateTime]::Now.AddDays(-1)
    $end = [System.DateTime]::Now.AddMonths(1)
    
    $sasToken = New-AzStorageAccountSasToken -Service blob,file,Table,Queue -ResourceType Service,Container,Object -Permission "racwdlup" -Protocol HttpsOnly -StartTime $start -ExpiryTime $end -Context $storageContext
    
    
    Set-AzKeyVaultManagedStorageSasDefinition -AccountName $storageAccountName -VaultName $keyVaultName -Name "<YourSASDefinitionName>" -TemplateUri $sasToken -SasType 'account' -ValidityPeriod ([System.Timespan]::FromDays(30))
    
    Set-AzKeyVaultAccessPolicy -VaultName $keyVaultName -ObjectId "Azure Function MSI object id" -PermissionsToSecrets get,list
    
      public static class Http
        {
            [FunctionName("Http")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
                ILogger log, ExecutionContext context)
            {
                var azureServiceTokenProvider = new AzureServiceTokenProvider();
                var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    
                SecretBundle sasToken =await kv.GetSecretAsync(secretIdentifier: "https://testkey02.vault.azure.net:443/secrets/teststorage08-sasToken");
                var storageCredential = new StorageCredentials(sasToken.Value);
                var accountsStorageName = "teststorage08";
                var storageAccount = new CloudStorageAccount(storageCredential, accountsStorageName, "core.windows.net", true);
    
                var tableClient = storageAccount.CreateCloudTableClient();
                var table =tableClient.GetTableReference("Customer");
                await table.CreateIfNotExistsAsync();
                CustomerEntity customer = new CustomerEntity("Harp", "Walter")
                {
                    Email = "Walter@contoso.com",
                    PhoneNumber = "425-555-0101"
                };
    
                TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(customer);
                TableResult result = await table.ExecuteAsync(insertOrMergeOperation);
                CustomerEntity insertedCustomer = result.Result as CustomerEntity;
    
                return new OkObjectResult(insertedCustomer);
    
            }       
        }
    
        public class CustomerEntity : TableEntity
        {
            public CustomerEntity()
            {
            }
    
            public CustomerEntity(string lastName, string firstName)
            {
                PartitionKey = lastName;
                RowKey = firstName;
            }
    
            public string Email { get; set; }
    
            public string PhoneNumber { get; set; }
        }