Заполните все необходимые поля в форме создания автоматизации и нажмите кнопку Создать
d. Импортировать AzureAD модуль и дождитесь успешного завершения процесса.
2. Создайте Рунные книги
a. Перейдите в свою учетную запись автоматизации, выберите Рунные книгии нажмите кнопку Создайте книгу выполнения.
b. Когда книга выполнения будет создана, нажмите Редактировать и вставьте свой сценарий PowerShell, затем нажмите кнопку Сохранить и Опубликовать.
3. Приведенный ниже сценарий можно использовать для повысить доступ пользователя к роли контрибьютора и запускает электронные письма при возникновении ошибок. Сначала сценарий проверяет, есть ли у пользователя роль Читателя, уже назначенная подписке, к которой он хочет получить повышенный доступ. Если нет, он выдаст ошибку. Если у пользователя уже есть роль Contributor на запрашиваемом ресурсе, он тоже выдаст ошибку.
Выделенные области следует адаптировать к особенностям вашей среды.
param ( [Parameter(Mandatory = $true)] [string] $subscriptionId, [Parameter(Mandatory = $true)] [string] $resourceGroupName, [Parameter(Mandatory = $true)] [string] $resourceName, [Parameter(Mandatory = $true)] [string] $resourceType, [Parameter(Mandatory = $true)] [string] $userPrincipalName, [Parameter(Mandatory = $false)] [string] $linkUrl )
$ErrorActionPreference = "Продолжить" $errors = @() function Send-Email($subject, $body, $to, $cc = $null, $isBodyHtml = $false) { $credential = Get-AutomationPSCredential -Name 'SMTP Relay' $smtpServer = 'smtp.example.com' $smtpPort = <Int32> $from = 'example@examplecompany.com' $mailParams = @{ Кому = $to Тема = $subject Тело = $body SmtpServer = $smtpServer Учетная запись = $credential Порт = $smtpPort UseSsl = $true From = $from BodyAsHtml = $isBodyHtml } if ($cc) { $mailParams['Cc'] = $cc } Send-MailMessage @mailParams -ErrorAction Stop } try { $connection = Connect-AzAccount -Identity } catch { $errors += "Не удалось пройти аутентификацию в Azure с помощью Managed Identity:$_" } try { Set-AzContext -SubscriptionId $subscriptionId } catch { $errors += "Не удалось установить контекст подписки Azure:$_" } $roleDefinitionName = 'Contributor' $readerRoleDefinitionName = 'Reader' попробуйте { $user = Get-AzADUser -UserPrincipalName $userPrincipalName -ErrorAction Stop } catch { $errors += "Failed to retrieve user object for UPN '$userPrincipalName': $_" } # Проверка наличия у пользователя роли читателя на уровне подписки $readerRoleAssignment = Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $readerRoleDefinitionName -Scope "/subscriptions/$subscriptionId" -ErrorAction SilentlyContinue if (-not $readerRoleAssignment) { $noReaderRoleHtml = @" <h2>Не в роли читателя</h2>
<p>Пользователь <strong>$userPrincipalName</strong> не имеет <strong>$readerRoleDefinitionName</strong> роль на уровне подписки и не может быть добавлена в <strong>$roleDefinitionName</strong> роль для ресурса.</p> "@ $noReaderRoleHtml += $signature Send-Email -subject "Missing Reader Role" -body $noReaderRoleHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true вернуть } # Проверьте, существует ли группа ресурсов $resourceGroupExists = $true $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue if (-not $resourceGroup) { $errors += "Группа ресурсов '$resourceGroupName' не существует." $resourceGroupExists = $false } # Проверьте, существует ли ресурс в группе ресурсов $domain = "yourdomain.onmicrosoft.com" # замените это на ваш фактический домен арендатора AAD # Проверьте, существует ли ресурс в группе ресурсов, используя имя и тип $resourceExists = $false $resourceUrl = "" if ($resourceGroupExists) { $resources = Get-AzResource -ResourceGroupName $resourceGroupName -ResourceType $resourceType -Name $resourceName -ErrorAction SilentlyContinue $resource = $resources | Where-Object { $_.ResourceType -eq $resourceType -and $_.Name -eq $resourceName } if ($resource) { $resourceExists = $true # Создайте URL, используя домен, группу ресурсов, тип ресурса и имя ресурса $resourceUrl = "https://portal.azure.com/#@$domain/resourcegroups/$resourceGroupName/providers/$($resource.ResourceType)/$resourceName" } else { $errors += "Ресурс типа '$resourceType' с именем '$resourceName' не существует в группе ресурсов '$resourceGroupName'." } } # Попытка назначения роли только при наличии группы ресурсов и ресурса if ($resourceGroupExists -and $resourceExists) { try { $roleAssignment = New-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction Stop } catch { if ($_.Exception -match 'Conflict') { # Пользователь уже имеет роль Contributor, отправьте конкретное письмо $alreadyContributorHtml = @" <h2>Пользователь уже внес вклад</h2> <p>Пользователь<strong>$userPrincipalName</strong>уже имеет<strong>$roleDefinitionName</strong>роль для ресурса<strong>$resourceName</strong>.</p> <p>URL ресурса:<a href='$linkUrl'>$linkUrl</a></p> "@ $alreadyContributorHtml += $signature Send-Email -subject "User Already Has Contributor Role" -body $alreadyContributorHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true } else { $errors += "Не удалось назначить роль '$roleDefinitionName' пользователю '$userPrincipalName': $_" } } } $signature = @" <p>С наилучшими пожеланиями,</p> <p><strong>Ваша команда ИТ-специалистов</strong></p> <p><em>Это автоматическое сообщение, пожалуйста, не отвечайте на него напрямую.</em></p> "@ if ($errors) { $errorMessageHtml = "<h2>Обнаружены проблемы при назначении ролей в Azure</h2><ul>" foreach ($errorItem в $errors) { $errorMessageHtml += "<li>$errorItem</li>" } $errorMessageHtml += "</ul>$signature" Send-Email -subject "Azure Role Assignment Issues" -body $errorMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true } elseif ($roleAssignment) { # Назначение роли прошло успешно, отправьте письмо об успехе $successMessageHtml = @"<h2>Успешное распределение ролей</h2> <p>Пользователь<strong>$userPrincipalName</strong>был успешно присвоен<strong>$roleDefinitionName</strong>роль для ресурса<strong>$resourceName</strong>.</p> <p>URL ресурса:<a href='$linkUrl'>$linkUrl</a></p> "@ $successMessageHtml += $signature Send-Email -subject "Azure Role Assignment Success" -body $successMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true }
Обратите внимание, что выполнение приведенных выше и ниже сценариев PowerShell обычно занимает около 5 минут, поскольку модулям AzureAD требуется время для загрузки.
Также обратите внимание, что при добавлении новой роли, например Contributor, пользователь должен выйти из системы и снова войти в Azure или использовать окно Incognito/Private, чтобы новая роль вступила в силу.
4. Необходимо создать вторую Runbook для удаления роли Contributor по истечении определенного периода времени.
Примером сценария PowerShell для этого является:
param ( [Parameter(Mandatory = $true)] [string] $subscriptionId, [Parameter(Mandatory = $true)] [string] $resourceGroupName, [Parameter(Mandatory = $true)] [string] $resourceName, [Parameter(Mandatory = $true)] [string] $resourceType, [Parameter(Mandatory = $true)] [string] $userPrincipalName, [Parameter(Mandatory = $false)] [string] $linkUrl ) $ErrorActionPreference = "Продолжить" $errors = @() $signature = @"
<p>С наилучшими пожеланиями,</p> <p><strong>Ваша команда ИТ-специалистов</strong></p> <p><em>Это автоматическое сообщение, пожалуйста, не отвечайте на него напрямую.</em></p> "@ function Send-Email($subject, $body, $to, $cc = $null, $isBodyHtml = $false) { $credential = Get-AutomationPSCredential -Name 'SMTP Relay' $smtpServer = 'smtp.example.com' $smtpPort =<int 32> $from = 'example@examplecompany.com' $mailParams = @{ Кому = $to Тема = $subject Тело = $body SmtpServer = $smtpServer Учетная запись = $credential Порт = $smtpPort UseSsl = $true From = $from BodyAsHtml = $isBodyHtml } if ($cc) { $mailParams['Cc'] = $cc } Send-MailMessage @mailParams -ErrorAction Stop } try { $connection = Connect-AzAccount -Identity } catch { $errors += "Не удалось пройти аутентификацию в Azure с помощью Managed Identity:$_" } try { Set-AzContext -SubscriptionId $subscriptionId } catch { $errors += "Не удалось установить контекст подписки Azure:$_" } $roleDefinitionName = 'Contributor' попробуйте { $user = Get-AzADUser -UserPrincipalName $userPrincipalName -ErrorAction Stop } catch { $errors += "Failed to retrieve user object for UPN '$userPrincipalName': $_" }
Не в роли читателя
# Проверьте, существует ли группа ресурсов, и получите ресурс $resourceGroupExists = $resourceExists = $false если ((Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue)) { $resourceGroupExists = $true $resources = Get-AzResource -ResourceGroupName $resourceGroupName -ResourceType $resourceType -Name $resourceName -ErrorAction SilentlyContinue $resource = $resources | Where-Object { $_.ResourceType -eq $resourceType -and $_.Name -eq $resourceName } if ($resource) { $resourceExists = $true } else { $errors += "Ресурс типа '$resourceType' с именем '$resourceName' не существует в группе ресурсов '$resourceGroupName'." } } else { $errors += "Группа ресурсов '$resourceGroupName' не существует." } # Попытка удалить назначение роли, если группа ресурсов и ресурс существуют if ($resourceGroupExists -and $resourceExists) { try { $roleAssignments = Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction SilentlyContinue foreach ($roleAssignment in $roleAssignments) { # Примечание: Подавление подтверждения будет работать, если команда поддерживает его. Remove-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -Confirm:$false } # Проверьте, успешно ли удалены назначения ролей if (-not (Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction SilentlyContinue)) { # Если удаление прошло успешно, отправьте сообщение об успехе $successMessageHtml = @"<h2>Удаление ролей Успех</h2> <p>Пользователь<strong>$userPrincipalName</strong>был успешно удален из<strong>$roleDefinitionName</strong>роль для ресурса<strong>$resourceName</strong>.</p> <p>URL ресурса:<a href='$linkUrl'>$linkUrl</a></p> "@ $successMessageHtml += $signature Send-Email -subject "Azure Role Removal Success" -body $successMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com " -isBodyHtml $true } else { $errors += "Роль '$roleDefinitionName' все еще существует для пользователя '$userPrincipalName' после попытки удаления." } } catch { $errors += "Не удалось удалить роль '$roleDefinitionName' у пользователя '$userPrincipalName': $_" } } if ($errors) { $errorMessageHtml = "<h2>Проблемы, обнаруженные при удалении ролей Azure</h2><ul>" foreach ($errorItem in $errors) { $errorMessageHtml += "<li>$errorItem</li>" } $errorMessageHtml += "</ul>$signature" Send-Email -subject "Azure Role Removal Issues" -body $errorMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true }
5. Предоставьте учетной записи автоматизации роль администратора доступа пользователей по подписке
a. Чтобы сценарий PowerShell можно было запустить, учетная запись автоматизации должна иметь роль администратора доступа пользователей.
b. Добавьте роль в каждая подписка для которых вы хотите разрешить запрос повышенного доступа.
c. В разделе Роль выберите Доступ пользователей Администратор затем нажмите Следующий.
d. В разделе Участники выберите Управляемая идентичность затем + Выберите членоввыберите Подписка где запущена учетная запись автоматизации, выберите управляемую идентификацию и участника в поле Select.
e. Выбранный член появится в нижней части экрана, затем нажмите кнопку Выберите и Просмотр + назначение.
f. Приложение Automation Account Enterprise Application теперь будет отображаться в подписке (подписках) как имеющее роль администратора доступа для пользователя под Контроль доступа (IAM)
6. Создайте форму Microsoft, запрашивающую URL-адрес ресурса и любую другую информацию, необходимую в соответствии с вашими бизнес-потребностями. В приведенном ниже примере мы попросим указать причину и количество часов, в течение которых требуется повышенный доступ к ресурсу, при этом из выпадающего списка можно выбрать максимум 8 часов.
7. Установите Группа безопасности в Офисный администратор
a. Назначьте участников, которым разрешено делать запрос на повышенный доступ. (Необязательно, но настоятельно рекомендуется - если вы не хотите выполнять эту проверку безопасности, перейдите к созданию потока ниже - шаг 9)
b.После создания группы безопасности обратите внимание на идентификатор группы безопасности, расположенный в URL. Например, идентификатор группы безопасности - это GUID, расположенный здесь:
https://admin.microsoft.com/Adminportal/Home#/groups/:/GroupDetails/хххххххххххххххххххххххххххххххххххххххххх/1
8. Зарегистрируйте приложение в portal.azure.com
a. Согласие администратора гранта к следующему Microsoft Graph Разрешения API с указанием типа Приложение:
-
-
- Каталог.Читать.Все
- Группа. Читать.Все
- Пользователь.Читать.Все
-
b. Создайте Секрет клиента для приложения и обратите внимание на ID арендатора... Идентификатор приложения (клиента) и секрет Значение для Потока.
8. Теперь настройте поток для обработки данных формы и выполнения сценариев PowerShell:
a. Триггер Microsoft Forms - При отправке нового ответа
b. Действие Microsoft Forms - Получение сведений об ответе из триггера responseId
c. Если вы пропустили рекомендацию группы безопасности, перейдите к шагу 10 ниже
I. Получение профиля пользователя (v2) с использованием триггерного ответчика в качестве пользователя (UPN)
II. Чтобы подтвердить, что пользователь входит в группу безопасности, создайте HTTP GET-запрос на URI: https://graph.microsoft.com/v1.0/groups/.ххххххххххххххххххххххххххххххххххх/transitiveMembers?$filter=id eq 'outputs('Get_user_profile_(V2) ')?['body/id']'&$select=id
III. В HTTP GET-запросе разверните Аутентификация и убедитесь, что Тип аутентификации Active Directory OAuthАудитория https://graph.microsoft.com/и чтобы значения, отмеченные при регистрации приложения в Azure, были добавлены в соответствующие поля:
IV. Отправить электронное письмо ИТ-администратору, если запрос отклонен, выполняется, если при проверке группы безопасности не удалось получить запись. После этого запросчику отправляется электронное письмо с уведомлением о том, что он не входит в группу безопасности, позволяющую сделать такой запрос.
V. Стоит отметить, что вышеуказанной проверкой безопасности можно управлять и непосредственно в доступе Microsoft Form, однако группа безопасности является более безопасным решением, требующим меньшего обслуживания:
10. Создайте условие, проверяющее, есть ли URL-адреса, предоставленные для получения повышенного доступа, в списке подписок, к которым вы разрешите им запрашивать повышенный доступ.
a. Чтобы разобрать подписку из предоставленного URL, используйте следующее выражение, заменив выделенное значение Get_response_details, указывающее на поле URL вашей формы:
first(split(last(split(body('Get_response_details')?['URLfieldID'],'/resource/subscriptions/')),'/resourceGroups/')
b. Если URL-адрес относится к подписке, которой нет в списке, отправьте отправителю письмо с отказом
c. Если URL-адрес содержит подписку в списке, перейдите к созданию задания Azure Automation
11. В действии Azure Automation заполните все выделенные значения, указав на Runbook, которая предоставляет повышенный доступ Contributor.
a. Subscription = Подписка, в которой находится Runbook
b. Группа ресурсов = Группа ресурсов, в которой находится книга выполнения
c. Учетная запись автоматизации = Учетная запись автоматизации, которая была настроена ранее b
d. Runbook Name = Имя рабочей книги для предоставления роли Contributor
e. После выбора Runbook появятся параметры сценария PowerShell, в которые можно добавить необходимые сведения. Чтобы разобрать эту информацию из URL, который был предоставлен при отправке формы:
I. SubscriptionId
first(split(last(split(body('Get_response_details')?['URLfieldID'],'/resource/subscriptions/')),'/resourceGroups/')
II. ResourceGroupName
first(split(last(split(body('Get_response_details')?['URLfieldID'],'/resourceGroups/'),'/providers/'))
III. ResourceGroupName
first(split(first(split(last(split(body('Get_response_details')?['URLfieldID'],'/providers/')),concat('/',last(split(body('Get_response_details')?['URLfieldID'],'/'))))),concat('/',last(split(first(split(last(split(body('Get_response_details')?['URLfieldID'],'/providers/')),concat('/',last(split(body('Get_response_details')?['URLfieldID'],'/'))))),'/')))))
IV. UserPrincipalName
body('Get_response_details')?['responder']
V. ResourceName
last(split(first(split(last(split(body('Get_response_details')?['URLfieldID'],'/providers/')),concat('/',last(split(body('Get_response_details')?['URLfieldID'],'/'))))),'/'))
VI. LinkUrl
body('Get_response_details')?['URLfieldID']
12. В этом примере мы позволяем пользователю определить, как долго ему нужен повышенный доступ. В параметре "Задержка" счетчик определяется числом, указанным в поле формы для часов, а единицей измерения является час.
13. После задержки мы создаем новое действие Azure Automation, на этот раз указывающее на Runbook, которое удаляет роль Contributor для пользователя на этом конкретном ресурсе.
a. Поля идентичны полям для предоставления роли Contributor, а также разбору соответствующих параметров.
Несколько идей, которые можно адаптировать или добавить к этому Потоку, которые мы не будем рассматривать:
- Используйте внутреннюю систему тикетов в качестве триггера, а не Microsoft Forms.
- Позвольте пользователю выбрать группу ресурсов и/или уровень доступа к подписке в зависимости от его потребностей. Учтите, что некоторые выражения парсинга при этом изменятся.
- Добавьте поток утверждения, отправляемый человеку или группе людей, которые имеют возможность утвердить или отклонить запрос.
Главный операционный директор в Connecting Software
Автор:
Я являюсь операционным директором компании Connecting Software, управляя повседневной деятельностью на различных предприятиях. Я увлечен постоянным совершенствованием и повышением эффективности. Если вы хотите присоединиться к нашей замечательной команде в Словакии или на Мадейре, пожалуйста, свяжитесь со мной.
Есть ли больше информации в Интернете?
Посмотрите другие статьи нашего блога о синхронизации сервера Exchange: