Есть ли способ защитить функцию Azure, которая будет вызываться только из определенного приложения логики Azure? - PullRequest
4 голосов
/ 29 марта 2019

Я понимаю, что функции Azure потенциально являются открытыми конечными точками в Интернете, если я правильно читаю документацию Microsoft и общаюсь с другом, у которого есть некоторый опыт работы с парадигмами веб-разработки, которые используются функциями Azure. Беглое чтение форумов по безопасности и вопросов переполнения стека по этой теме позволяет мне понять, по крайней мере, несколько вариантов их защиты, а именно: 1) Azure Active Directory 2) Подписи общего доступа (SAS) и 3) Виртуальные сети Azure .

Контекст / Что делает моя функция Azure? Он управляет контейнером больших двоичных объектов, связанным с ETL данных поставщика, из источника SFTP в конечную точку SQL, в которой этот ETL использует промежуточный контейнер больших двоичных объектов для передачи файлов и долгосрочного холодного хранения исходных данных. Функция Azure перемещает большие двоичные объекты из одного контейнера в контейнер архива после их загрузки в конечную точку SQL. Зачем Azure Function управлять контейнерами больших двоичных объектов? 1) В SSIS отсутствует возможность выполнять операции с большими двоичными объектами (т. Е. Копировать и удалять). 2) В приложении логики отсутствует возможность выполнения объединения (файлов, загруженных в конечную точку SQL, и имен файлов в контейнере больших двоичных объектов).

Пример одной из функций ниже:

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

1 Ответ

6 голосов
/ 29 марта 2019

Во-первых, хотя использование ключей может быть удобным, я вижу, что официальная документация не рекомендует использовать ключи для защиты конечной точки функции в производственных сценариях.

enter image description here

Я полагаю, что было бы лучше выбрать Azure Active Directory для обеспечения безопасности ... как описано здесь Защищать конечную точку HTTP на производстве

Как реализовать

Я вижу два возможных подхода:

1. Простой подход: убедитесь, что вызывающее приложение - это ваше логическое приложение Azure, в частности

Включите аутентификацию Azure Active Directory для вашего функционального приложения Azure. Вы можете просто использовать настройки Express (с созданием нового приложения Azure AD)

Включение идентификатора управляемой службы для вашего приложения логики.

Найдите appid для идентификатора управляемой службы, связанного с вашим приложением логики. Перейдите на портал Azure> Azure Active Directory> Корпоративные приложения> Все приложения> Соответствующий принципал службы (более подробно объяснено со скриншотами в еще одна статья SO здесь )

Аутентификация приложения логики в функции Azure с использованием идентификатора управляемой службы, как описано здесь. Аутентификация с использованием управляемого идентификатора в приложении логики .. обратите внимание, что доступ к ресурсу будет вашей функцией Azure.

enter image description here

В коде вашей функции теперь вы можете проверить, что утверждение appid в токене доступа должно точно соответствовать appid для приложения логики (т. Е. Приложение логики - это приложение, вызывающее вашу функцию). В противном случае вы можете отклонить вызов с помощью Несанкционированное исключение.

2. Более декларативный подход: определите разрешение приложения для приложения-функции Azure и проверьте наличие этого разрешения / роли в маркере авторизации от клиента, вызывающего вашу функцию

Этот подход немного более декларативен, поскольку вы определяете разрешение приложения, которое должно быть назначено любому приложению, которое может вызывать вашу функцию Azure.

Включите аутентификацию Azure Active Directory для вашего функционального приложения Azure. Вы можете просто использовать настройки 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>

Аутентификация вашего логического приложения в функции Azure с использованием идентификатора управляемой службы ... как уже объяснено в подходе 1 выше

Теперь в токене авторизации, полученном вашей функцией, вы можете проверить, что коллекция утверждений role должна содержать роль с именем "MyFunctionValidClient", в противном случае вы можете отклонить вызов с неавторизованным исключением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...