有没有一种方法可以保护只能从特定Azure Logic应用程序调用的Azure功能?

时间:2019-03-28 22:46:23

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

我了解,如果我正确阅读Microsoft的文档并与具有一定经验的朋友交谈,则Azure可能是Internet上的开放端点,该朋友具有一些使用Azure Functions进行Web开发范例的经验。粗略阅读安全论坛和有关该主题的堆栈溢出问题使我理解至少有两种方法可以保护它们,即1)Azure Active Directory 2)Shared Access Signatures (SAS)和3)Azure Virtual Networks。 / p>

上下文/我的Azure函数做什么?它管理与从SFTP源到SQL端点的供应商数据的ETL相关的Blob容器,该ETL使用中间Blob容器进行文件传输和源数据的长期冷存储。将Blob加载到SQL终结点后,Azure函数将这些Blob从一个容器移动到存档容器。为什么使用Azure Function管理Blob容器?:1)SSIS缺乏执行Blob操纵(即复制和删除)的能力2)Logic App缺乏执行联接(加载到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")
            };
        }
    }
}

3 个答案:

答案 0 :(得分:5)

首先,尽管使用键可能很方便,但我发现official documentation建议不要在生产场景中使用键来保护功能端点。

enter image description here

我建议使用Azure Active Directory以获得更好的安全性。如此处Secure an HTTP endpoint in production

所述

如何实施

我看到两种可能的方法:

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

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

为您的逻辑应用程序启用托管服务身份。

查找与您的逻辑应用程序关联的托管服务身份的appid。.转到Azure门户> Azure Active Directory>企业应用程序>所有应用程序>相关服务主体(another SO post here中的屏幕截图详细说明)< / p>

使用托管服务身份将逻辑应用授权到Azure功能,如此处所述。.Authenticate with managed identity in logic app ..请注意,被访问的资源将是您的Azure功能。

enter image description here

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

2。一种更具声明性的方法:为Azure函数应用程序定义应用程序权限,并从客户端调用您的函数的auth令牌中检查此权限/角色是否存在

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

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

现在转到Azure Active Directory>应用程序注册>功能应用程序的应用程序注册>清单

enter image description here

使用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>

如上文方法1中所述,使用托管服务身份将逻辑应用授权到Azure功能。

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

答案 1 :(得分:0)

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

转到该函数的Host.json。 默认authLevel:“功能”应更改为“ authLevel”:“匿名”。

这并不意味着任何人都可以像登录AD登录身份验证所需的登录用户那样访问该功能,但是在逻辑应用程序功能中具有托管身份的用户可以使用服务原理进行身份验证。

答案 2 :(得分:0)

看看这篇文章。

http://www.codeninjango.com/programming/azure/securing-http-triggered-azure-functions/

只需几个简单的步骤即可启动并使用HTTP触发的功能上的主机密钥和一个不错的示例。