【问题标题】:Is there a way to secure an Azure Function that will only be called from a specific Azure Logic App?有没有办法保护只能从特定 Azure 逻辑应用调用的 Azure 函数?
【发布时间】:2019-08-19 20:03:54
【问题描述】:

如果我正确阅读了 Microsoft 的文档并与一位在使用 Azure Functions 所利用的 Web 开发范例方面有一定经验的朋友交谈,我了解 Azure Functions 可能是 Internet 上的开放端点。粗略阅读有关该主题的安全论坛和堆栈溢出问题使我至少了解了几个保护它们的选项,即

  1. Azure Active Directory
  2. Shared Access Signatures (SAS)
  3. Azure Virtual Networks

上下文/我的 Azure 函数有什么作用?它管理与从 SFTP 源到 SQL 端点的供应商数据的 ETL 相关的 blob 容器,该 ETL 利用中间 blob 容器进行文件传输和源数据的长期冷存储。 Azure 函数在将 Blob 加载到 SQL 终结点后将其从一个容器移动到存档容器。为什么选择 Azure Function 来管理 blob 容器?

  1. SSIS 缺乏执行 blob 操作(即复制和删除)的能力
  2. 逻辑应用无法执行连接(加载到 SQL 端点的文件和 blob 容器中的文件名)

其中一个函数的示例如下所示:

using System.IO;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net;
using Microsoft.WindowsAzure.Storage.Blob;
using System.Collections.Generic;
using System.Text;

namespace AFA_ArchiveBlob
{
    public static class HttpTrigger_BlobInput
    {
        [FunctionName("HttpTrigger_BlobInput")]
        public static async Task<HttpResponseMessage> Run(
        //public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get",  Route = "{name}")] HttpRequest req,
            string name,
            ILogger log,
            [Blob("{name}/blobname",FileAccess.ReadWrite,Connection = "AzureWebJobsStorage")]  CloudBlobContainer myCloudBlobContainer
            )
        {
            //Execution Logged.
            log.LogInformation($"HttpTrigger_BlobInput - C# HTTP trigger function processed a request.");

            //Run the query against the blob to list the contents.
            BlobContinuationToken continuationToken = null;
            List<IListBlobItem> results = new List<IListBlobItem>();
            do
            {
                var response = await myCloudBlobContainer.ListBlobsSegmentedAsync(continuationToken);
                continuationToken = response.ContinuationToken;
                results.AddRange(response.Results);
            }
            while (continuationToken != null);

            //Query the names of the blobs. Todo: can this be a single line linq query select instead?
            List<string> listBlobNames = new List<string>();
            foreach (CloudBlockBlob b in results)
            {
                listBlobNames.Add(b.Name);
            }

            //Serialize the list of blob names to json for passing to function caller via return statement
            var jsonReturn = JsonConvert.SerializeObject(listBlobNames);

            log.LogInformation("Returning the following JSON");
            log.LogInformation(jsonReturn);

            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(jsonReturn, Encoding.UTF8, "application/json")
            };
        }
    }
}

【问题讨论】:

    标签: azure security azure-active-directory azure-functions azure-logic-apps


    【解决方案1】:

    首先,尽管使用密钥可能很方便,但我看到official documentation 建议不要在生产场景中使用密钥来保护函数端点。

    我建议使用 Azure Active Directory 来确保安全性会是一个更好的选择。正如此处所述Secure an HTTP endpoint in production

    如何实施

    我看到了两种可能的方法:

    1.简单方法:检查调用应用程序是否是您的 Azure 逻辑应用程序

    为您的 Azure Function App 启用 Azure Active Directory 身份验证。您可以简单地使用 Express 设置(通过创建新的 Azure AD 应用程序)

    为您的逻辑应用启用托管服务标识。

    找出与逻辑应用关联的托管服务标识的 appid。转到 Azure 门户 > Azure Active Directory > 企业应用程序 > 所有应用程序 > 相关服务主体(在another SO post here 中使用屏幕截图进行了更详细的说明)

    使用托管服务标识向 Azure 函数验证您的逻辑应用,如此处所述。Authenticate with managed identity in logic app.. 请注意,正在访问的资源将是您的 Azure 函数。

    在您的函数代码中,现在您可以检查访问令牌中的appid 声明是否应与逻辑应用程序的appid 完全匹配(即逻辑应用程序是调用您的函数的那个​​).. 否则您可以拒绝调用未经授权的异常。

    2。更具声明性的方法:为 Azure 函数应用定义应用程序权限,并检查此权限/角色是否存在于来自调用您的函数的客户端的身份验证令牌中

    这种方法更具声明性,因为您定义了一个应用程序权限,该权限需要分配给任何可以调用您的 Azure 函数的应用程序。

    为您的 Azure Function App 启用 Azure Active Directory 身份验证。您可以简单地使用 Express 设置(通过创建新的 Azure AD 应用程序)

    现在转到 Azure Active Directory > 应用注册 > 函数应用的应用注册 > 清单

    添加一个新的应用程序角色.. 像这样使用 json:

    "appRoles": [
    {
      "allowedMemberTypes": [
        "Application"
      ],
      "displayName": "Can invoke my function",
      "id": "fc803414-3c61-4ebc-a5e5-cd1675c14bbb",
      "isEnabled": true,
      "description": "Apps that have this role have the ability to invoke my Azure function",
      "value": "MyFunctionValidClient"
    }]
    

    为您的逻辑应用启用托管服务标识。

    找出与您的逻辑应用关联的托管服务标识的 appid。如上面方法 1 中所述

    将应用权限分配给此托管服务身份..

    New-AzureADServiceAppRoleAssignment -ObjectId <logicappmsi.ObjectId> -PrincipalId <logicappmsi.ObjectId> -Id "fc803414-3c61-4ebc-a5e5-cd1675c14bbb" -ResourceId <yourfunctionaadapp.ObjectId>
    

    使用托管服务标识向 Azure 函数验证您的逻辑应用。如上面方法 1 中所述

    现在,在您的函数收到的身份验证令牌中,您可以检查 role 声明集合是否必须包含名为 "MyFunctionValidClient" 的角色,否则您可以拒绝未授权异常的调用。

    【讨论】:

    • 说的很详细,看起来不错。明天我会参加社交活动并阅读您引用的所有文档,如果我从您的回复中学到任何东西,请告诉您。亲爱的朋友!
    • @rohitsaigal Weird,“在生产中保护 http 端点”的链接不再有效,但我记得几周前读过它。那么它去哪儿了?
    【解决方案2】:

    除了@Rohit 解释的上述步骤之外,以下步骤很重要:

    转到函数的 Host.json。 默认 authLevel : "function" 应改为 "authLevel": "anonymous"。

    这并不意味着任何人都可以使用登录 AD 登录身份验证所需的签名用户访问该功能,但是使用逻辑应用功能中的托管身份使用服务原则进行身份验证。

    【讨论】:

      猜你喜欢
      • 2021-08-04
      • 2019-04-25
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 1970-01-01
      • 2020-01-03
      • 2018-10-30
      • 1970-01-01
      相关资源
      最近更新 更多