Azure: автоматизация назначения Azure Policy для настройки Log Analytics скриптами Azure PowerShell



Обещанные «очень технические» видео по теме Azure на канале – пришло время поделиться некоторыми из личных скриптов и заложенных в них идеях и особенностях реализации той или иной функциональности Azure. В этом видео/посте – поговорим про реализацию автоматического назначения некоторых Azure Policy для конфигурации отправки различными объектами диагностики в Azure Log Analytics при помощи скриптов Azure PowerShell.


Azure: автоматизация назначения Azure Policy для настройки Log Analytics скриптами Azure PowerShell

Почему не с применением ARM Template? – да потому, что «заморочек» в работе с политиками через ARM Template, особенно если говорить о назначении имеющихся политик, да еще и в режиме «исправления» Remediation. Это и огромные нечитаемые «простыни» самого ARM Template вероятными ошибками при копи-пасте и «заморочками» при редактировании, и масса вопросов по описанию в том же (или отдельном) шаблоне всех необходимых учетных записей managed identity (principal) с раздачей им необходимых ролей в том же шаблоне, и процесс поиска и прописывания массы параметров вручную и прочие моменты типа «ручного участия» даже в назначении имен в том же шаблоне… Потому – скрипт, который управляет назначением выбранных политик – является куда меньшим «злом» с точки зрения процесса и более универсальным в работе, чем шаблоны, которые нужно потом очень внимательно править.

И напомню про пару  других моих детальных видео об автоматизации Azure с применением скриптов (с детальным разбором данных скриптов):

  • · Azure – подробный обзор универсального PowerShell скрипта для работы с Azure Log Analytics API – https://youtu.be/2AB-bIQl_4Q
  • · Закон Мерфи для кода или автоматическое копирование файлов между Azure Storage с Azure Logic Apps – https://youtu.be/jvWX6V92aCQ

Но вернемся к представленному Azure PowerShell скрипту, в задачу которого входит назначение политик (стандартных, встроенных в Azure) настройки мониторинга Azure Log Analytics для всех типов сервисов Azure, которые поддерживают данные настройки, на уровне выбранной подписки Azure (хотя в качестве области назначения политик может быть и ресурсная группа, и Management Group). В качестве политики используются встроенные политики Azure Policy, которые соответствуют шаблону имени ‘*diagnostic settings*Log Analytics*’, которые развертываются в режиме Remediation (effect = DeployIfNotExists) для своего типа сервисов.

Какие важные блоки в данном скрипте, на что обратить внимание при работе с назначением политик и использованием их в режиме Remediation (исправления) в коде Azure PowerShell:

  • · Простые операции получения списка нужных политик (или инициатив – набора политик) при помощи команды
    $mons = Get-AzPolicyDefinition | Where-Object { $_.Properties.DisplayName -like ‘*diagnostic settings*Log Analytics*’ }
    и работы с данным списком в цикле для каждого элемента.
  • · Проверка параметров для политики – напомню, что у политики есть свои параметры – большинство из которых – например, тот же режим работы политики – параметр Effect – является установленным по умолчанию в рекомендуемое значение, но вот для данного случая существует еще и параметр logAnalytics (которым назначается конкретное хранилище Log Analytics Workspace, куда направляются все логи) и который может иметь различные модификации имен. Потому – в скрипте проводится проверка точного имени параметра по шалону ‘logAnalytics*’ и формирование параметра на основе полученного имени.

    # get right name of policy’s parameter (typicaly named as logAnalytics or logAnalytics_1 or logAnalytics_param ) to setup required Log Analytics as destination storage
    $obj = $mon.Properties.Parameters
    $prop = Get-Member -InputObject $obj -MemberType NoteProperty -Name logAnalytics*
    # build parameter object
    if($prop)
    {
    $asparam = @{$($prop[0].Name)=$($logan.ResourceId)}
    }

  • · Формирование имени для назначения конкретной политики на основе строки описания политики, из которой по шаблонам извлекается название сервиса (описания для всех политик по управлению настройками диагностики стандартные и позволяют достаточно просто получить имя сервиса, для которого политика предназначена), для которого назначается политика, и после, используя полученное название – создается имя типа $name = “{0}-monitoring-assigned-byScript” -f $aname

    # Build the name of assignment based on substring with Azure service type in Policy’s description
    $aname = $mon.Properties.Description.Split(‘ for ‘)[1].Split(‘ to stream ‘)[0]
    $aname = $aname.Replace(‘ ‘, ”)
    # Workaround for some non-standard descriptions 🙂
    if($aname.Length -gt 32)
    {
    $aname = $mon.Properties.Description.Split(‘ for ‘)[1].Split(‘ and stream the logs to ‘)[0]
    $aname = $aname.Replace(‘ ‘, ”)
    }
    $name = “{0}-monitoring-assigned-byScript” -f $aname

  • · Назначение политики в режиме Remediation – обязательное указание параметров локации (параметр команды -Location) и привязки managed identity (-AssignIdentity) – $assignment = New-AzPolicyAssignment -Name $name -PolicyDefinition $mon -Scope $subsId -PolicyParameterObject $asparam -Location westeurope -AssignIdentity
  • · Ожидание создания учетной записи, привязанной к назначенной политики – требуется время, чтобы вновь созданная учетная запись была реплицирована внутри Azure AD и была доступна – поскольку без этого нельзя назначать требуемые роли на следующем шагу.

    # Assignment have to create Service Principal account and we need to check was account created before continue.
    # The new managed identity must complete replication through Azure Active Directory before it can be granted the needed roles.
    $prid = $assignment.Identity.PrincipalId
    $principal = Get-AzADServicePrincipal -ObjectId $prid
    while(!$principal -and $null -eq $principal)
    {
    Start-Sleep -s 10
    $principal = Get-AzADServicePrincipal -ObjectId $prid
    }

  • · Самая важная часть скрипта – при назначении политик через портал Azure выполняет операции по конфигурированию связанной учетной записи – назначение ролей – на фоне в автоматическом режиме, но когда используется PowerShell – команда New-AzPolicyAssignment только создает учетную запись, но не назначает для нее роли, которые потом требуются для выполнения политикой операций по исправлению конфигураций. Потому скрипт берет данные о ролях из описания политик (внутри каждой политики есть описание требуемых ролей (ID) для операций Remediation) и назначает роли для вновь созданных учетных записей. В случае, если речь идет не просто о политике, а об инициативе (наборе политик) – то тут скрипт просматривает еще и набор политик внутри каждой инициативы и уже из описания политики извлекает ID требуемых ролей (об этом вы найдете в конце видео, когда идет сравнение двух скриптов – для назначения политик и инициатив)

    # WARNING!!! workaround for assignment of the policy that requires remediation
    <#

When creating an assignment using the portal, Azure Policy both generates the managed identity and grants it the roles defined in roleDefinitionIds.

In the following conditions, steps to create the managed identity and assign it permissions must be done manually:

While using the SDK (such as Azure PowerShell)

When a resource outside the assignment scope is modified by the template

When a resource outside the assignment scope is read by the template

The following code iterates the policy definition in $policyDef for the roleDefinitionIds and uses New-AzRoleAssignment to grant the new managed identity the roles.

#>

# Get all policy’s definitions inside each policy in Initiative

$polDefs = $mon.policyDefinitionId

foreach( $polDef in $polDefs)

{

$policyDef = Get-AzPolicyDefinition -Id $polDef

# Use the $policyDef to get to the roleDefinitionIds array

$roleDefinitionIds = $policyDef.Properties.policyRule.then.details.roleDefinitionIds

if ($roleDefinitionIds.Count -gt 0)

{

$roleDefinitionIds | ForEach-Object {

$roleDefId = $_.Split(“/”) | Select-Object -Last 1

New-AzRoleAssignment -Scope $subsId -ObjectId $assignment.Identity.PrincipalId -RoleDefinitionId $roleDefId

}

}

}

  • · И, в заключение – назначение задачи по сканированию конфигурации существующих экземпляров сервисов на соответствие политике и исправлению (Remediation), если данное исправление требуется. Так же, как и в предыдущем случае, при назначении политики через интерфейс портала Azure – данная операция назначается в мастере назначения, а в случае использования скриптов – операция Remediation должна быть назначена отдельной командой явно. Кроме того, чтобы следить за ходом выполнения сканирования и исправления – скрипт выводит на экран текст команды с требуемым ID задачи.

    # Create a remediation for a specific assignment


$name = “Remediation_{0}-monitoring-assigned-byScript” -f $aname

$remtask = Start-AzPolicyRemediation -Name $name -PolicyAssignmentId $assignment.ResourceId -ResourceDiscoveryMode ReEvaluateCompliance

Start-Sleep -s 30

Get-AzPolicyRemediation -Id $remtask.Id

Write-Host “`r`nRemediation task $($remtask.Id) was configured!`r`n`t>>> Check state (ProvisioningState property) by >>> ‘Get-AzPolicyRemediation -Id $($remtask.Id)’ command`r`n”

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

Полный исходный код обоих скриптов, рассмотренных в видео – найдете в аттачменте к данном посту.


Другие доклады по облачным и серверным технологиям у меня на канале:

  • · ИТ-карьера – “ОТКРЫТОЕ СОБЕСЕДОВАНИЕ” – начинаем новый сезон 2021 – приглашаются все желающие – https://youtu.be/h0hk03xX_Z0
  • · Azure AZ-900 – онлайн семинар MUK – построение гибридной инфры с Azure Arc и Windows Admin Center – https://youtu.be/vJhuo7bc-Pg
  • · Azure AZ-900 – онлайн семинар MUK – Azure Security Center – обзор возможностей и конфигурирование – https://youtu.be/1Z3Z6XqJZsM
  • · Azure AZ-900-онлайн семинар MUK-Azure Infrastructure as Code IaC, ARM templates, BICEP, Azure DevOps – https://youtu.be/UOEmloeetfY
  • · Azure AZ-900 – онлайн семинар MUK – Microsoft Power Virtual Agents – создание эффективных чат-ботов – https://youtu.be/mez50o_m0oE
  • · Azure SALES – онлайн-семинар MUK – продажа сервисов Azure для различных сценариев кибербезопасности – https://youtu.be/YF7yKgCVLAA
  • · Azure AZ-900 – онлайн-семинар MUK – обзор Azure Automation, Monitor, Log Analytics, Logic Apps – https://youtu.be/a6VGeDUNYt4
  • · Azure SALES – онлайн-семинар MUK – что такое PaaS службы баз данных Azure SQL и Azure Data Platform – https://youtu.be/38Y-TxFFqT4
  • · Azure SALES – онлайн-семинар MUK – планирование миграции в Azure, стоимость и службы гибридой инфра – https://youtu.be/j_LqwHeLDPY
  • · Azure – онлайн-семинар MUK – планирование миграции в Azure с Azure Migrate, построение гибридой инфра – https://youtu.be/vnQOSPrunKc
  • · Закон Мерфи для кода или автоматическое копирование файлов между Azure Storage с Azure Logic Apps – https://youtu.be/jvWX6V92aCQ
  • · Azure Global AI Bootcamp (UAE) – рус.версия по Cognitive services с PowerShell, Functions, Logic Apps – https://youtu.be/7J4veWZqtpY
  • · Azure – онлайн-семинар MUK – использование сервисов Azure (Logic Apps, Functions, Cognitive) для RPA – https://youtu.be/YQiCfiivpBc
  • · Azure – онлайн-семинар MUK – основы Power Platform создание решений на Power Apps, Flows, Chatbots – https://youtu.be/DECMirInQ2I
  • · Что такое облачные технологии и подготовка к экзамену Microsoft AZ-900 Azure Fundamentals – http://bit.ly/Exam-Az-900

Microsoft Azure Functions на PowerShell–включение аутентификации пользователя для HTTP Trigger, получаем информацию об аутентификации пользователя в коде функции на PowerShell и про “поддержку” Microsoft.


Начнем с технической части повествования – чтобы народу было интересно и полезно почитать, а уже потом перейдем к «политическо-ИТшной» – это уже по желанию, но как по мне так смешно, что аж печально… 😉

Итак, в некоем решении используются Azure Functions, написанные на PowerShell Core (потому что все мои админы знакомы и легко могут модифицировать, развивать решение при необходимости) и в качестве безопасности (аутентификации пользователей) работающие со стандартной идентификацией от Azure AD при вызове того, что называется Http Trigger, т.е. функции, имеющей свой персональный URL, по которому ее и можно запустить, передав требуемые параметры.

Требуется – при развитии решения появилась потребность не только аутентифицировать пользователей, но и иметь некие аналоги аудита (кто какие функции вызывает) и ролевой модели (запрет некоторым людям вызывать функции или использовать глобальные параметры).

Аутентификация на базе Azure AD для Azure Functions включается в пару кликов и не требует какого-либо изменения кода самой Azure Functions – для функции вся аутентификация работает при описанном ниже сценарии «прозрачно», всю работу по аутентификации на себя берет «движок» Azure. Не путать, кстати, с опцией Identity, которая позволяет имперсонализировать сам исполняемый экземпляр Azure Functions в Azure и выполнять код под определенным аккаунтом в Azure, которому можно предоставлять разные права – чем, собственно, мы и пользуемся – используя Azure Functions для выполнения различных задач обслуживания, предоставляя толпе из L1 для выполнения базовых операций не доступ к порталу Azure и клиентским подпискам, а только к функциям, которые уже все сделают «как нужно и правильно»…

Но вернемся к аутентификации пользователей при вызове Azure Functions. Итак:

Заходим на основную страницу требуемой Azure Functions, переключаемся в закладку Platform Features, и там кликаем на опцию Authentication / Authorization

clip_image002

На открывшейся странице устанавливаем переключатель App Service Authentication в положение On и в появившемся ниже выпадающем списке Action to take when request is not authenticated выбираем опцию Log in with Azure Active Directory, а в следующем списке Authentication Providers кликаем на пункт Azure Active Directory / Not Configured

clip_image004

Откроется новое окно настроек – создания экземпляра приложения для аутентификации в Azure AD, где в Managed Mode выбираем опцию Express и далее, в появившихся ниже опциях, выбираем правильный каталог Azure AD (если в вашем профиле их несколько зарегистрировано), Managed Mode оставляем, как есть – Create New AD App – и оставляем имя по умолчанию.

clip_image006

Кликаем Ok в данном диалоге, ждем окончания процесса создания объекта, и в форме Authentication / Authorization, куда вас вернет портал, кликаем вверху на иконку Save. Опять таки – ждем окончания операции и получаем сконфигурированное приложение с аутентификацией от Azure AD. Теперь, при обращении к Azure Functions, которые зарегистрированы, как Http Trigger, Azure будет запрашивать у вызывающего пройти аутентификацию и предъявить аккаунт пользователя из указанной выше Azure Active Directory. Так что анонимные пользователи такую функцию теперь не вызовут.

НО! Такой сценарий достаточен только для «отсечения» анонимных пользователей, а вот если требуется какое-либо подобие RBAC внутри самих Azure Functions – например, пользователь аутентифицируется, но при этом часть параметров функции ему недоступна или доступ к данным внутри самой функции должен быть ограничен – здесь, увы, такая аутентификация не поможет. Да и вообще, у Azure нет толкового RBAC для Functions.

Т.е. после вызова функции вызов перенаправляется на аутентификацию в Azure AD и если все ок – управление передается на Azure Functions и нам надо теперь внутри исполняемой функции получить клейм пользователя и все атрибуты его учетной записи – ID в аутентифицирующей системе, имя, саму систему и прочие токены. При этом все это еще требуется получить в PowerShell.

И тут начинается самое интересное – хотя Microsoft со всех трибун кричит про внедрение Serverless решений, рассказывает про использование Azure Functions вместе с PowerShell для процессов автоматизации – в реальности никакой официальной документации от Microsoft, особенно фундаментальной, по теме Functions/PowerShell вы не найдете. В Интернете ее тоже нет, даже на любимом всеми StackOverflow – просто никто не использует решение, не смотря на громкие заявления Microsoft.

Нашел пару документов про работу с идентити/информацией аутентификации в Functions/Web Apps применительно к C#, но это нагромождение классов и вызовов было явно не релевантно для кода PowerShell. Чтобы понять всю глубину проблемы, стоит сказать, что ни я, ни моя команда – ни разу не девелоперы – только PowerShell скрипты для автоматизации процессов заказчиков и auto-healing, только хардкор, как, например, скриптик PowerShell на 1000 строк для правильного «развертывания всего» с соответствующими внутренностями VM. Для нас вообще удивительно, кстати, почему работа с тем же Azure Storage Queues в PowerShell пишется в 3 строки, а в C# сначала надо создать десяток классов при неочевидном выигрыше в производительности самой Functions. Но это уже лирика, а вывод простой – для людей, которые занимаются автоматизацией процессов на PowerShell, документации по разработке на сайте Microsoft совершенно недостаточно, приходится собирать по крупицам с разных источников, работать «методом тыка» или открыть тикет в саппорте. На том и порешили – продолжаем «копать» и обращаемся в саппорт.

Методом логического анализа кода («методом тыка») на C# обнаружилось, что чтобы работать cо всей информацией по аутентификации пользователя, вызывающего Functions с аутентификацией в Azure AD (как настроено выше) в PowerShell коде можно через Headers одной командой:

$Request.Headers

Ниже – представленный в JSON объект заголовка вызова Http Trigger в Azure Functions (тот самый $Request.Headers). Все поля, как на ладони и далее работаем с ними, как с обычным hashtable в PowerShell, т.е. получаем нужное значение по имени ключа (которым являются поля заголовка ниже).

clip_image008

Т.е., чтобы получить имя пользователя, его ID, его Access Token и т.п. в коде PowerShell – требуется максимум 1-2 команды:

$headersObj = $Request.Headers # get call’s headers

$username = $headersObj[“x-ms-client-principal-name”]   # get user account name

$userid = $headersObj[“x-ms-client-principal-id”]       # get user AAD ID

$userip = $headersObj[“x-forwarded-for”]                # get user IP

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


И тут начинается вторая часть истории – которая смешная и печальная, особенно в разрезе предыдущей моей истории про то, как Microsoft Ukraine заблокировала и удалила мои видео по курсу для сертификации AZ-900 по Azureпродолжения истории c Microsoft Ukraine после).

Итак, открыл я кейс в Microsoft support по данной проблеме и вот выдержка переписки:

1. Я описываю проблему

clip_image010

2. И получаю от Microsoft Support ответ, что в моем сценарии (option 1, процесс конфигурирования которого и описан выше) такую информацию получить нельзя:

clip_image012

3. Причем, получив такой ответ – я уже 100% уверен в возможности получения этих данных, просто еще не имею на руках конкретного кода. И я отправляю письмо типа – «точно нельзя с опцией 1? Уверены?» и получаю от Microsoft support еще один отрицательный ответ – нет, вы не можете получить такую информацию (причем, происходит это через 5 дней, три из которых – рабочие):

clip_image014

4. И в ответ на это дело я уже пишу, что нашел сценарий, код из 2х строк работает и можно закрывать кейс.

И вот тут начинается самое интересное и «смешное». Мне сразу же перезванивает (буквально в течение 15 минут, до этого отвечал только по почте и то – через сутки) сотрудник службы поддержки Microsoft, который просит поделиться с ними решением проблемы и кодом!!! Т.е. Microsoft, который до этого активно удалял мои технические видео про Azure из принадлежащей мне группы в Facebook, а потом и удалил мой аккаунт из админов – про это читайте тут и тут – теперь вдруг другой рукой просит поделиться информацией со своей поддержкой?! Серьезно?! Я должен бесплатно делать за сотрудников Microsoft их работу? Той информацией, которую Microsoft в качестве базовой просто обязан опубликовать в документации, поскольку и продукт – платный, и везде, со всяких трибун, Microsoft кричит о важности безопасности вообще и правильного кода – в частности. И уж точно этой информацией должна владеть служба поддержки Microsoft…

Чтобы вам было еще смешнее – я и сейчас продолжаю получать письма с просьбами отдать код, последнее пришло уже сегодня, 25 декабря, через 9 дней после того, как я сообщил, что задача имеет решение. Вот реально?! За 9 дней внутри Microsoft собственный отдел поддержки не смог найти техническое решение и продолжает ждать у моря погоды – поделюсь ли я кодом?!

clip_image016

И самое смешное – Microsoft за последние 3-5 лет сократил практически весь высококвалифицированный технический персонал из своих локальных офисов ввиду того, что Azure поддержки не требует, его надо только продавать, а технической поддержкой пусть занимаются партнеры «за деньги». Azure, как показывает опыт, просто за бла-бла-бла девочек из маркетинга Microsoft не продается (про это я говорю тоже в первой серии курса AZ-900), а партнеры, при таких отношении, «экспертизе», «документации» и «поддержке» от Microsoft – точно не будут вкладываться в «прибыльный и простой бизнес Azure» и не будут развивать компетенции Azure, как и клиенты не горят желанием платить деньги «каким-то партнерам», один раз столкнувшись с подобным невежеством поддержки «самого Microsoft». И, особенно, партнерам не интересно это делать, если развитие компетенций не интересно самому Microsoft и даже поддержка Microsoft не в состоянии дать ответ на простой, как оказалось, вопрос.

И если объективно смотреть на ситуацию c поддержкой Azure, то можно смело сказать, исходя из своего опыта работы С Microsoft последние пару лет, что никакой реальной поддержки и технической компетенции «на местах» у Microsoft сейчас просто нет. Выгребайте сами. И иметь у себя классного специалиста по Azure в штате – это будет даже лучше и безопаснее, чем вам пришлют какого-то «технического консультанта» от Microsoft, который в реальности окажется «не пойми кто», как я уже писал во второй части большого поста про Microsoft.

Но и это еще не все про Microsoft и поддержку Azure… Читайте в следующем посте про развертывание Windows кластеров в Azure и про официальные скрипты от Microsoft.

Друге видео то теме Azure и ИТ-карьеры: