Automatisieren von Azure Resource Elevated Role Requests mit Power Automate und Azure Automation

Automatisieren von Azure Resource Elevated Role Requests mit Power Automate und Azure Automation

Adam MaurerTechnical Leave a Comment

Image
1. Erstellen Sie innerhalb eines Azure-Abonnements Ihrer Wahl eine Automation Account-Ressource, indem Sie portal.azure.com besuchen und Alle Ressourcen und klicken Sie hinzufügen.

a. Suchen Sie nach "Automatisierung" und klicken Sie auf erstellen.

Automatisierung

Füllen Sie alle erforderlichen Felder im Formular zur Erstellung der Automatisierung aus und klicken Sie auf erstellen

Image

b. Importieren Sie die AzureAD-Module
c. Öffnen Sie dazu das soeben erstellte Automatisierungskonto, wählen Sie Module unter Gemeinsame Ressourcen, wählen Sie Galerie durchsuchenund suchen Sie nach AzureAD.

Module

d. Importieren Sie die AzureAD und warten Sie, bis der Vorgang erfolgreich abgeschlossen ist.

2. Erstellen Sie Laufbücher

a. Navigieren Sie zu Ihrem Automatisierungskonto, wählen Sie Laufbücherund klicken Sie auf Ein Runbook erstellen.

Rubriken

b. Wenn das Runbook erstellt ist, klicken Sie auf bearbeiten und fügen Sie Ihr PowerShell-Skript ein, dann klicken Sie auf Speichern und veröffentlichen..


3. Das folgende Skript kann verwendet werden, um den Zugriff eines Benutzers auf die Contributor-Rolle erhöhen und löst E-Mails aus, wenn Fehler auftreten. Das Skript prüft zunächst, ob der Benutzer dem Abonnement, auf das er erweiterten Zugriff erhalten möchte, bereits eine Leserrolle zugewiesen hat. Ist dies nicht der Fall, wird ein Fehler ausgegeben. Wenn der Benutzer bereits eine Contributor-Rolle für die angeforderte Ressource hat, tritt auch hier ein Fehler auf.

Die hervorgehobenen Bereiche sollten an die Details Ihrer Umgebung angepasst werden.

param (
[Parameter(Obligatorisch = $true)]
[string] $subscriptionId,
[Parameter(Obligatorisch = $true)]
[string] $resourceGroupName,
[Parameter(Pflichtfeld = $true)]
[string] $resourceName,
[Parameter(Pflichtfeld = $wahr)]
[string] $resourceType,
[Parameter(Pflichtfeld = $true)]
[string] $userPrincipalName,
[Parameter(Pflichtfeld = $false)]
[string] $linkUrl
)
$ErrorActionPreference = "Weiter" $errors = @() function Send-Email($subject, $body, $to, $cc = $null, $isBodyHtml = $false) { $credential = Get-AutomationPSCredential -Name 'SMTP-Relay' $smtpServer = smtp.example.com'. $smtpPort = <Int32> $von = 'example@examplecompany.com' $mailParams = @{ An = $to Betreff = $subject Nachricht = $body SmtpServer = $smtpServer Zugangsdaten = $credential Anschluss = $smtpAnschluss UseSsl = $true Von = $from BodyAsHtml = $isBodyHtml } if ($cc) { $mailParams['Cc'] = $cc } Send-MailMessage @mailParams -ErrorAction Stop } try { $connection = Connect-AzAccount -Identity } catch { $errors += "Authentifizierung bei Azure mit Managed Identity fehlgeschlagen:$_" } try { Set-AzContext -SubscriptionId $subscriptionId } catch { $errors += "Azure-Abonnementkontext konnte nicht gesetzt werden:$_" } $roleDefinitionName = 'Mitwirkender' $readerRoleDefinitionName = 'Leser' try { $user = Get-AzADUser -UserPrincipalName $userPrincipalName -ErrorAction Stop } catch { $errors += "Failed to retrieve user object for UPN '$userPrincipalName': $_" } # Prüfen, ob der Benutzer die Rolle "Leser" auf der Abonnementebene hat $readerRoleAssignment = Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $readerRoleDefinitionName -Scope "/subscriptions/$subscriptionId" -ErrorAction SilentlyContinue if (-not $readerRoleAssignment) { $noReaderRoleHtml = @" <h2>Nicht in der Leserrolle</h2>
<p>Benutzer <strong>1TP57BenutzerPrinzipalName</strong> hat nicht die <strong>$readerRoleDefinitionName</strong> Rolle auf der Abonnementebene und kann nicht zum <strong>$roleDefinitionName</strong> Rolle für die Ressource.</p> "@ $noReaderRoleHtml += $signature Send-Email -subject "Fehlende Leserrolle" -body $noReaderRoleHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true return } # Prüfen, ob die Ressourcengruppe existiert $resourceGroupExists = $true $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue wenn (-not $resourceGroup) { $errors += "Die Ressourcengruppe '$resourceGroupName' existiert nicht." $resourceGroupExists = $false } # Prüfen, ob die Ressource innerhalb der Ressourcengruppe existiert $domain = "ihredomain.onmicrosoft.de"# ersetzen Sie dies durch Ihre tatsächliche AAD-Mieterdomäne # Prüfen Sie, ob die Ressource innerhalb der Ressourcengruppe existiert, indem Sie sowohl den Namen als auch den Typ verwenden $resourceExists = $false $resourceUrl = "" wenn ($resourceGroupExists) { $resources = Get-AzResource -ResourceGroupName $resourceGroupName -ResourceType $resourceType -Name $resourceName -ErrorAction SilentlyContinue $resource = $resources | Where-Object { $_.ResourceType -eq $resourceType -und $_.Name -eq $resourceName } if ($resource) { $resourceExists = $true # Konstruieren Sie die URL unter Verwendung der Domäne, der Ressourcengruppe, des Ressourcentyps und des Ressourcennamens $resourceUrl = "https://portal.azure.com/#@$domain/resourcegroups/$resourceGroupName/providers/$($resource.ResourceType)/$resourceName" } else { $errors += "Ressource vom Typ '$resourceType' mit dem Namen '$resourceName' existiert nicht in der Ressourcengruppe '$resourceGroupName'." } } # Versuch der Rollenzuweisung nur, wenn Ressourcengruppe und Ressource existieren if ($resourceGroupExists -und $resourceExists) { try { $roleAssignment = New-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction Stop } catch { if ($_.Exception -match 'Conflict') { # Benutzer hat bereits die Contributor-Rolle, senden Sie eine spezielle E-Mail $alreadyContributorHtml = @" <h2>Benutzer Bereits ein Contributor</h2>             <p>Benutzer<strong>1TP57BenutzerPrinzipalName</strong>hat bereits die<strong>$roleDefinitionName</strong>Rolle für Ressource<strong>1TP57Ressourcenname</strong>.</p>             <p>Ressourcen-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 += "Rolle '$roleDefinitionName' konnte dem Benutzer '$userPrincipalName' nicht zugewiesen werden: $_" } } } $signatur = @" <p>Mit freundlichen Grüßen,</p> <p><strong>Ihr IT-Team</strong></p> <p><em>Dies ist eine automatische Nachricht, bitte antworten Sie nicht direkt auf diese E-Mail.</em></p> "@ wenn ($errors) { $errorMessageHtml = "<h2>Erkannte Probleme bei der Azure-Rollenzuweisung</h2><ul>" foreach ($errorItem in $errors) { $errorMessageHtml += "<li>$errorItem</li>" } $errorMessageHtml += "</ul>$signatur" Send-Email -subject "Probleme mit der Azure-Rollenzuweisung" -body $errorMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true } elseif ($roleAssignment) { # Rollenzuweisung war erfolgreich, senden Sie eine Erfolgs-E-Mail $successMessageHtml = @"<h2>Rollenzuweisung Erfolg</h2>     <p>Benutzer<strong>1TP57BenutzerPrinzipalName</strong>wurde erfolgreich mit dem<strong>$roleDefinitionName</strong>Rolle für Ressource<strong>1TP57Ressourcenname</strong>.</p>     <p>Ressourcen-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 }

Bitte beachten Sie, dass die oben und unten aufgeführten PowerShell-Skripte in der Regel ca. 5 Minuten bis zur Fertigstellung benötigen, da die AzureAD-Module Zeit zum Laden benötigen.

Beachten Sie auch, dass sich der Benutzer beim Hinzufügen einer neuen Rolle, wie z. B. Contributor, abmelden und wieder bei Azure anmelden oder ein Inkognito/Privatfenster verwenden sollte, damit die neue Rolle wirksam wird.

4. Ein zweites Runbook sollte erstellt werden, um die Contributor-Rolle zu entfernen, wenn ein bestimmter Zeitraum verstrichen ist.

Ein Beispiel für ein PowerShell-Skript für diesen Zweck ist:

  param (
[Parameter(Obligatorisch = $true)]
[string] $subscriptionId,
[Parameter(Obligatorisch = $true)]
[string] $resourceGroupName,
[Parameter(Pflichtfeld = $true)]
[string] $resourceName,
[Parameter(Pflichtfeld = $wahr)]
[string] $resourceType,
[Parameter(Pflichtfeld = $true)]
[string] $userPrincipalName,
[Parameter(Pflichtfeld = $false)]
[string] $linkUrl
)

$ErrorActionPreference = "Weiter"
$errors = @()
$signatur = @" 

<p>Mit freundlichen Grüßen,</p> <p><strong>Ihr IT-Team</strong></p> <p><em>Dies ist eine automatische Nachricht, bitte antworten Sie nicht direkt auf diese E-Mail.</em></p> "@ function Send-Email($subject, $body, $to, $cc = $null, $isBodyHtml = $false) { $credential = Get-AutomationPSCredential -Name 'SMTP-Relay' $smtpServer = 'smtp.beispiel.de' $smtpPort =<int 32> $from = 'example@examplecompany.com' $mailParams = @{ An = $to Betreff = $subject Nachricht = $body SmtpServer = $smtpServer Zugangsdaten = $credential Anschluss = $smtpAnschluss UseSsl = $true Von = $from BodyAsHtml = $isBodyHtml } if ($cc) { $mailParams['Cc'] = $cc } Send-MailMessage @mailParams -ErrorAction Stop } try { $connection = Connect-AzAccount -Identity } catch { $errors += "Die Authentifizierung bei Azure mit Managed Identity ist fehlgeschlagen:$_" } try { Set-AzContext -AbonnementId $subscriptionId } catch { $errors += "Azure-Abonnementkontext konnte nicht gesetzt werden:$_" } $roleDefinitionName = 'Mitwirkender' try { $user = Get-AzADUser -UserPrincipalName $userPrincipalName -ErrorAction Stop } catch { $errors += "Failed to retrieve user object for UPN '$userPrincipalName': $_" }

Nicht in der Leserrolle

# Prüfen, ob die Ressourcengruppe existiert und die Ressource abrufen
$resourceGroupExists = $resourceExists = $false
wenn ((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 -und $_.Name -eq $resourceName }

if ($resource) {

$resourceExists = $true

} else {
$errors += "Ressource vom Typ '$resourceType' mit dem Namen '$resourceName' existiert nicht in der Ressourcengruppe '$resourceGroupName'."
}
} else {

$errors += "Die Ressourcengruppe '$resourceGroupName' existiert nicht."
}

# Versuch, die Rollenzuweisung zu entfernen, wenn Ressourcengruppe und Ressource existieren

if ($resourceGroupExists -und $resourceExists) {
try {

$roleAssignments = Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction SilentlyContinue

foreach ($roleAssignment in $roleAssignments) {

# Hinweis: Die Bestätigungsunterdrückung funktioniert, wenn das Cmdlet sie unterstützt.
Remove-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -Confirm:$false

}

# Prüfen, ob Rollenzuweisungen erfolgreich entfernt wurden
if (-not (Get-AzRoleAssignment -ObjectId $user.Id -RoleDefinitionName $roleDefinitionName -Scope $resource.ResourceId -ErrorAction SilentlyContinue)) {

# Wenn die Entfernung erfolgreich war, eine Erfolgs-E-Mail senden
$successMessageHtml = @"<h2>Erfolg bei der Rollenentfernung</h2> 
            <p>Benutzer<strong>1TP57BenutzerPrinzipalName</strong>wurde erfolgreich aus dem<strong>$roleDefinitionName</strong>Rolle für Ressource<strong>1TP57Ressourcenname</strong>.</p>
            <p>Ressourcen-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 += "Die Rolle '$roleDefinitionName' existiert noch für den Benutzer '$userPrincipalName' nach dem Entfernungsversuch."
}

} catch {
$errors += "Fehler beim Entfernen der Rolle '$roleDefinitionName' von Benutzer '$userPrincipalName': $_"
}

}

if ($errors) {
$errorMessageHtml = "<h2>Erkannte Probleme bei der Entfernung von Azure-Rollen</h2><ul>"
foreach ($errorItem in $errors) {
$errorMessageHtml += "<li>$errorItem</li>"
}
$errorMessageHtml += "</ul>$signatur"
  Send-Email -subject "Probleme bei der Entfernung von Azure-Rollen" -body $errorMessageHtml -to $userPrincipalName -cc "itadministrator@examplecompany.com" -isBodyHtml $true

} 

5. Geben Sie dem Automatisierungskonto die Rolle Benutzerzugriffsadministrator pro Abonnement

a. Damit das PowerShell-Skript ausgeführt werden kann, muss das Automatisierungskonto die Rolle "User Access Administrator" haben.
b. Hinzufügen einer Rolle in jedes Abonnement für die ein erweiterter Zugang beantragt werden soll.
c. Wählen Sie im Abschnitt Rolle Benutzerzugang Administrator dann klicken Nächste.

add-role-assignment

d. Wählen Sie im Abschnitt Mitglieder Verwaltete Identität dann + Mitglieder auswählenwählen Sie die Abonnement wo das Automatisierungskonto ausgeführt wird, wählen Sie die verwaltete Identität und das Mitglied im Feld Auswählen.

e. Das ausgewählte Mitglied wird am unteren Rand des Bildschirms angezeigt, und klicken Sie dann auf Wählen Sie und Überprüfen + zuweisen.

Image

f. Die Automation Account Enterprise-Anwendung ist nun in den Abonnements als Benutzer mit der Rolle Access Administrator unter Zugangskontrolle (IAM)

Image

6. Erstellen Sie ein Microsoft-Formular, in dem Sie die URL der Ressource und alle anderen Informationen, die Sie je nach Ihren geschäftlichen Anforderungen benötigen, abfragen. Im folgenden Beispiel fragen wir nach dem geschäftlichen Grund und der Anzahl der Stunden, die man einen erhöhten Zugriff auf die Ressource benötigt, wobei maximal 8 Stunden aus der Dropdown-Liste ausgewählt werden können.

azure-abonnement-zugriff-anforderung

7. Einrichten einer Gruppe Sicherheit in Büroverwaltung

a. Weisen Sie die Mitglieder zu, die berechtigt sind, die erhöhte Zugriffsanfrage zu stellen. (Optional, aber dringend empfohlen - Wenn Sie diese Sicherheitsprüfung nicht durchführen möchten, fahren Sie mit der Flow-Erstellung unten fort - Schritt 9)

aktive-teams-und-gruppen

b. Sobald die Sicherheitsgruppe erstellt ist, notieren Sie sich die Sicherheitsgruppen-ID, die sich in der URL befindet. Die ID der Sicherheitsgruppe ist zum Beispiel die hier angegebene GUID:

https://admin.microsoft.com/Adminportal/Home#/groups/:/GroupDetails/xxxxxxxx-xxxx-xxxx-xxxxxxxx-xxxxxxxx/1

8. Registrieren Sie eine Anwendung in portal.azure.com

a. Erteilung der Zustimmung der Verwaltung zum Folgenden Microsoft Grafik API-Berechtigungen mit Typ Anmeldung:

      • Verzeichnis.Lesen.Alle
      • Gruppe. Lesen.Alle
      • Benutzer.Lesen.Alle
config-permissions

b. Erstellen Sie eine Geheimnis des Kunden für die Anwendung und notieren Sie sich die Mieter-IDdie Anwendungs-(Kunden-)ID und das Geheimnis Wert für den Flow.

Kundengeheimnisse

8. Richten Sie nun einen Fluss ein, um die Formulardaten zu verarbeiten und die PowerShell-Skripte auszuführen:

a. Microsoft Forms-Auslöser - Wenn eine neue Antwort übermittelt wird

b. Microsoft Forms-Aktion - Abrufen von Antwortdetails aus dem Auslöser responseId

c. Wenn Sie die Empfehlung der Sicherheitsgruppe übersprungen haben, fahren Sie mit Schritt 10 unten fort

I. Abrufen des Benutzerprofils (v2) unter Verwendung des Trigger-Responders als Benutzer (UPN)

II. Um zu überprüfen, ob der Benutzer Teil der Sicherheitsgruppe ist, erstellen Sie eine HTTP-GET-Anfrage an URI: https://graph.microsoft.com/v1.0/groups/xxxxxxxx-xxxx-xxxx-xxxxxxxx-xxxxxxxx/transitiveMembers?$filter=id eq 'outputs('Get_user_profile_(V2) ')?['body/id']'&$select=id

Grafik-teil01

III. Erweitern Sie in der HTTP-GET-Anfrage das Feld Authentifizierung und stellen Sie sicher, dass der Authentifizierungstyp Active Directory OAuth, Publikum ist https://graph.microsoft.com/und dass die notierten Werte, die Sie bei der Registrierung der Anwendung in Azure angegeben haben, zu den jeweiligen Feldern hinzugefügt werden:

Formular

IV. Eine E-Mail an den IT-Administrator senden, wenn die Anfrage abgelehnt wurde, wird ausgeführt, wenn die Sicherheitsgruppenüberprüfung einen Datensatz nicht findet. Dann wird eine E-Mail an den Antragsteller gesendet, in der er darüber informiert wird, dass er nicht zu der Sicherheitsgruppe gehört, die einen solchen Antrag stellen kann.

Image

V. Es ist erwähnenswert, dass die oben genannte Sicherheitsprüfung auch direkt im Zugriff auf das Microsoft-Formular verwaltet werden kann, aber die Sicherheitsgruppe ist die sicherere Lösung, die weniger Wartung erfordert:

Einstellungen

10. Erstellen Sie eine Bedingung, um zu prüfen, ob die URLs, die für den erweiterten Zugriff angegeben wurden, in der Liste der Abonnements enthalten sind, für die Sie den Benutzern erlauben, erweiterten Zugriff anzufordern.

Image

a. Um das Abonnement aus der angegebenen URL zu analysieren, verwenden Sie den folgenden Ausdruck, wobei Sie den hervorgehobenen Wert Get_response_details ersetzen, der auf das URL-Feld Ihres Formulars zeigt:

first(split(last(split(body('Get_response_details')?['URLfieldID'],'/resource/subscriptions/')),'/resourceGroups/'))

b. Wenn die URL für ein nicht aufgeführtes Abonnement ist, senden Sie eine Ablehnungs-E-Mail an den Einsender

c. Wenn die URL ein Abonnement in der Liste enthält, fahren Sie mit der Erstellung eines Azure Automation-Jobs fort

11. Geben Sie in der Azure-Automatisierungsaktion alle hervorgehobenen Werte ein und verweisen Sie auf das Runbook, das den erweiterten Zugriff von Contributor gewährt.

a. Abonnement = Das Abonnement, in dem sich das Runbook befindet

b. Ressourcengruppe = Ressourcengruppe, in der sich das Runbook befindet

c. Automatisierungskonto = Das Automatisierungskonto, das zuvor eingerichtet wurde b

d. Runbook Name = Name des Runbooks, das die Contributor-Rolle gewährt

e. Sobald das Runbook ausgewählt ist, werden die Parameter aus dem PowerShell-Skript aufgefüllt, damit Sie die erforderlichen Details hinzufügen können. So analysieren Sie diese Informationen aus der URL, die bei der Formularübermittlung angegeben wurde:

I. AbonnementId

first(split(last(split(body('Get_response_details')?['URLfieldID'],'/resource/subscriptions/')),'/resourceGroups/'))

II. Name der Ressourcengruppe

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. Ressourcenname

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']

form02
Beachten Sie, dass ResourceType technisch nicht erforderlich ist, damit das Skript ausgeführt werden kann nur, wenn Sie eine Namenskonvention haben, die sicherstellt, dass jeder Ressourcenname innerhalb einer Ressourcengruppe eindeutig ist. Um Fehler bei der Zuweisung der Contributor-Rolle zu vermeiden, wird empfohlen, sie im Skript zu belassen.

12. In diesem Beispiel kann der Benutzer festlegen, wie lange er einen erhöhten Zugang benötigt. Bei der Verzögerung wird die Anzahl durch die im Formularfeld für Stunden angegebene Zahl definiert, während die Einheit Stunde ist.

13. Nach der Verzögerung erstellen wir eine neue Azure Automation-Aktion, die diesmal auf das Runbook verweist, das die Contributor-Rolle für den Benutzer auf dieser bestimmten Ressource entfernt.

a. Die Felder sind identisch mit den Feldern, die für die Vergabe der Contributor-Rolle benötigt werden, sowie mit dem Parsing für die entsprechenden Parameter.

Es gibt einige Ideen, die an diesen Flow angepasst oder hinzugefügt werden können, auf die wir aber nicht eingehen werden:

  1. Verwenden Sie Ihr internes Ticketingsystem als Auslöser anstelle von Microsoft Forms
  2. Erlauben Sie dem Benutzer, je nach Bedarf den Zugriff auf die Ressourcengruppe und/oder die Abonnementebene zu wählen. Beachten Sie, dass sich dabei einige Parsing-Ausdrücke ändern werden.
  3. Fügen Sie einen Genehmigungsfluss hinzu, der an eine Person oder eine Gruppe von Personen gesendet wird, die die Möglichkeit haben, die Anfrage zu genehmigen oder abzulehnen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.