Seb*_*olg 5 azure azure-storage azure-active-directory botframework azure-functions
随着宣布Azure存储支持基于Azure Active Directory的访问控制,是否可以仅通过URI通过Web浏览器提供Blob(特定文件)?
我想简化的用例是使一些人可以访问blob上的文件,而无需将SAS令牌附加到URI。相反,当尝试在其Web浏览器中打开普通URI时启动典型的OAuth流程将是很不错的选择。
就我而言,我们希望授予用户通过基于Microsoft Bot框架构建的支持bot上载到blob存储的文件的权限。支持代理应该在他们选择的Web浏览器中访问我们支持系统中的链接。
是此公告支持的该用例,还是仅适用于编码的OAuth流,这意味着我们仍然必须实现一些代码?
如果是这样,是否有一个很好的示例,说明如何从Azure Function应用启动OAuth流程并使用生成的令牌下载文件(通过Azure Storage REST终结点)?
虽然这个答案在技术上是正确的,但它并不是对我最初的问题的直接回应。
我一直在寻找一种方法来向业务用户提供任何 blob 的直接 uri,以便他们可以简单地在任何 Web 浏览器中打开它并查看文件。
就我而言,我们希望允许访问用户通过我们的支持机器人上传到 blob 存储的文件,该机器人基于 Microsoft Bot 框架构建。例如,将附件作为我们支持系统中的链接提供给支持代理访问。
深入研究后,我可以回答我自己的问题:
随着 Azure 存储支持基于 Azure Active Directory 的访问控制的公告,是否可以仅通过 URI 通过 Web 浏览器提供 blob(特定文件)?
不,这是不可能的。更具体地说,简单地在浏览器中打开指向 blob 的直接 uri 不会触发 OAuth 流程。相反,ResourceNotFound
除非您提供 SAS 查询令牌或将 blob 设置为公共,否则它始终会给您响应。从安全角度来看,这两种解决方案都很糟糕(当涉及普通用户时),而且明显糟糕的用户体验。
寻找一种方法来实现我想要的东西,我想出了一个 azure 函数的想法,通过传递fileName
as url 参数并使用路由模板构造路径来为任何业务用户提供附件。
考虑到安全性和对访问令牌的需求,您可以通过平台身份验证(又名 easyAuth)来保护功能应用程序。
然而,这还不够,配置解决方案的所有部分也不是一蹴而就的。这就是我分享它的原因。
TL;DR 高级步骤:
additionalLoginParams
令牌响应和 resourceId关于 Azure Storage API 权限和访问令牌的说明(步骤 5 & 6)
如Azure 存储上 AAD 身份验证支持的最新文档所述,应用程序必须拥有user_impersonation
resourceId 的大权限范围https://storage.azure.com/
。不幸的是,文档没有说明如何设置此 API 权限,因为它在门户中不可见(至少我没有找到)。
因此,唯一的方法是通过直接在 azure 门户中编辑应用程序注册清单,通过其全局 GUID(可在 Internet 上找到)进行设置。
更新: 事实证明,在门户中找不到正确的权限是一个错误。在这里看到我的答案。手动修改清单的结果相同,但直接在门户中进行修改要方便得多。
"requiredResourceAccess": [
{
"resourceAppId": "e406a681-f3d4-42a8-90b6-c2b029497af1",
"resourceAccess": [
{
"id": "03e0da56-190b-40ad-a80c-ea378c433f7f",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6",
"type": "Scope"
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
第一个是user_impersonation
Azure 存储上的范围,第二个是 的图形权限User.Read
,这在大多数情况下是有用的或需要的。
上传修改后的清单后,您可以在应用注册的API 权限选项卡上进行验证。
由于 easyAuth 使用 AAD 的 v1 端点,您的应用程序需要通过resource=https://storage.azure.com/
在触发 OAuth 流时传递来静态请求这些权限。
此外,Azure 存储需要用于身份验证标头的承载架构,因此需要 JWT 令牌。要从端点获取 JWT 令牌,我们需要response_type=code id_token
作为附加登录参数传递。
两者都只能通过Azure 资源浏览器或 Powershell 完成。
使用 Azure 资源浏览器,您必须一直导航到函数应用上的 authSettings 并进行additionalLoginParams
相应设置。
"additionalLoginParams": [
"response_type=code id_token",
"resource=https://storage.azure.com/"
]
Run Code Online (Sandbox Code Playgroud)
代码示例
这是使用上述所有机制的简单 azure 函数的完整代码示例。
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
namespace Controller.Api.v1.Org
{
public static class GetAttachment
{
private const string defaultContentType = "application/octet-stream";
[FunctionName("GetAttachment")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "v1/attachments")] HttpRequest req,
ILogger log)
{
if (!req.Query.ContainsKey("fileName"))
return new BadRequestResult();
// Set the file name from query parameter
string fileName = req.Query["fileName"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
fileName = fileName ?? data?.name;
// Construct the final uri. In this sample we have a applicaiton setting BLOB_URL
// set on the function app to store the target blob
var blobUri = Environment.GetEnvironmentVariable("BLOB_URL") + $"/{fileName}";
// The access token is provided as this special header by easyAuth.
var accessToken = req.Headers.FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase));
// Construct the call against azure storage and pass the user token we got from easyAuth as bearer
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value.FirstOrDefault());
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.Add("Accept", "*/*");
client.DefaultRequestHeaders.Add("x-ms-version", "2017-11-09");
// Serve the response directly in users browser. This code works against any browser, e.g. chrome, edge or even internet explorer
var response = await client.GetAsync(blobUri);
var contentType = response.Content.Headers.FirstOrDefault(p => p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
var byteArray = await response.Content.ReadAsByteArrayAsync();
var result = new FileContentResult(byteArray, contentType.Value.Any() ? contentType.Value.First() : defaultContentType);
return result;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果要对存储使用基于 Azure Active Directory 的访问控制,则需要获取访问令牌。以下是步骤供您参考。
2.为该应用程序分配一个内置的 RBAC 角色这取决于您要为该应用程序分配哪个角色。
3.获取访问令牌。
4.有了access token,现在就可以调用storage rest api了。
归档时间: |
|
查看次数: |
1174 次 |
最近记录: |