כדי ליצור אפליקציית Microsoft Azure ב-Azure Portal שתתמוך בהעברת נתונים מאובטחת מ-Exchange Online (Microsoft 365) לחשבון Google Workspace, צריך לפעול לפי השלבים הבאים. אפשר לבחור באחת משתי השיטות הבאות:
שימוש בסקריפט PowerShell להגדרת חיבור אוטומטי
כדי לבצע את השלבים האלה, אתם צריכים להיות אדמינים עם תפקיד גלובלי או תפקיד עם הרשאות.
לפני שמתחילים: צריך להתקין את Install-Module Microsoft.Graph -Scope CurrentUser.
אפשרות 1: שימוש ב-Azure Cloud Shell
- נכנסים ל-Microsoft Azure Portal בתור אדמין.
- לוחצים על Cloud Shell
Powershell.
- אם תופיע בקשה, תצטרכו ליצור חשבון אחסון ולאשר את הגדרות ברירת המחדל.
- מדביקים את הפקודה Install-Module Microsoft.Graph -Scope CurrentUser ולוחצים על Enter.
- אם מופיעה בקשה להתקנה ממאגר לא מהימן, מקלידים Y ואז לוחצים על Enter.
- מעתיקים את בלוק הקוד שבהמשך, מדביקים אותו ב-PowerShell ולוחצים על Enter.
<# .SYNOPSIS Automates the creation of a Single-Tenant Entra ID App for Workspace Migration. Strictly forces account selection and verifies specific Admin roles. #> # Check if the module is missing if (-not (Get-Module -ListAvailable -Name Microsoft.Graph.Authentication)) { Write-Host "Microsoft Graph module is NOT installed." -ForegroundColor Yellow $UserResponse = Read-Host "Would you like to try installing Microsoft Graph? (Y/N)" if ($UserResponse -ieq "Y") { try { # Use only native cmdlets, no .NET property setting Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force -AllowClobber Write-Host "Installation complete!" -ForegroundColor Green } catch { Write-Error "Policy is blocking installation. Please contact IT to install Microsoft.Graph module." Read-Host "Press Enter to exit"; exit } } else { exit } } else { Write-Host "Microsoft Graph modules detected. Proceeding..." -ForegroundColor Green } # --- STEP 0: THE "DEEP" LOGOUT --- Write-Host "Forcing session cleanup..." -ForegroundColor Gray Disconnect-MgGraph -ErrorAction SilentlyContinue # Force clear the local token cache folder if it exists $CachePath = "$env:USERPROFILE\.mg" if (Test-Path $CachePath) { try { Remove-Item $CachePath -Recurse -Force -ErrorAction SilentlyContinue } catch {} } Write-Host "Opening Microsoft Login... (Please select the correct account)" -ForegroundColor Cyan $RequiredScopes = @( "Application.ReadWrite.All", "AppRoleAssignment.ReadWrite.All", "Directory.Read.All", "RoleManagement.Read.Directory" ) try { # In v2, -ContextScope Process is the most reliable way to force account selection # and prevent the session from saving to the machine permanently. Connect-MgGraph -Scopes $RequiredScopes -ContextScope Process $Context = Get-MgContext if ($null -eq $Context) { throw "Login was cancelled or failed." } $UserPrincipal = $Context.Account Write-Host "Logged in as: $UserPrincipal" -ForegroundColor Green # --- ROLE VALIDATION --- Write-Host "Verifying Directory Roles..." -ForegroundColor Gray $UserRoles = Get-MgUserMemberOf -UserId $Context.Account -All | Where-Object { $_.AdditionalProperties.displayName -ne $null } $Authorized = $false $RequiredRoles = @("Global Administrator", "Privileged Role Administrator") foreach ($role in $UserRoles) { $roleName = $role.AdditionalProperties.displayName if ($roleName -in $RequiredRoles) { $Authorized = $true Write-Host "Access Granted: $roleName" -ForegroundColor Green break } } if (-not $Authorized) { Write-Host "`nCRITICAL ERROR: Insufficient Privileges." -ForegroundColor Red Write-Host "Account must be 'Global Administrator' or 'Privileged Role Administrator'." -ForegroundColor Yellow Disconnect-MgGraph Read-Host "`nPress Enter to exit"; exit } } catch { Write-Error "Login failed: $_" Read-Host "Press Enter to exit"; exit } # --- USER INPUT --- Write-Host "`n--- APPLICATION SETUP ---" -ForegroundColor Cyan $InputName = Read-Host "Enter the name for your new Entra ID Application (Default: Workspace Migration App)" $AppName = if ([string]::IsNullOrWhiteSpace($InputName)) { "Workspace Migration App" } else { $InputName } # --- CONFIGURATION --- $PermissionMap = @{ "calendar.read" = "Calendars.Read" "mail.read" = "Mail.Read" "contacts.read" = "Contacts.Read" "directory.read" = "Directory.Read.All" } $TenantId = $Context.TenantId $GraphAppId = "00000003-0000-0000-c000-000000000000" try { # --- STEP 1: REGISTER APPLICATION --- Write-Host "Creating Application: $AppName..." -ForegroundColor Cyan $Application = New-MgApplication -BodyParameter @{ displayName = $AppName signInAudience = "AzureADMyOrg" } # --- STEP 2: PREPARE SERVICE PRINCIPAL --- $NewServicePrincipal = New-MgServicePrincipal -BodyParameter @{ appId = $Application.AppId } Write-Host "Waiting 10 seconds for replication..." -ForegroundColor DarkGray Start-Sleep -Seconds 10 # --- STEP 3: CONFIGURE & GRANT PERMISSIONS --- Write-Host "Configuring API Permissions & Granting Admin Consent..." -ForegroundColor Cyan $GraphSP = Get-MgServicePrincipal -Filter "AppId eq '$GraphAppId'" | Select-Object -First 1 $ResourceAccessList = @() foreach ($key in $PermissionMap.Keys) { $RealRoleName = $PermissionMap[$key] $Role = $GraphSP.AppRoles | Where-Object { $_.Value -eq $RealRoleName } if ($Role) { $ResourceAccessList += @{ id = $Role.Id; type = "Role" } New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $NewServicePrincipal.Id -BodyParameter @{ principalId = $NewServicePrincipal.Id resourceId = $GraphSP.Id appRoleId = $Role.Id } | Out-Null Write-Host " - Granted: $RealRoleName" -ForegroundColor Gray } } Update-MgApplication -ApplicationId $Application.Id -RequiredResourceAccess @(@{ resourceAppId = $GraphAppId resourceAccess = $ResourceAccessList }) # --- STEP 4: CREATE CLIENT SECRET --- Write-Host "Generating Client Secret..." -ForegroundColor Cyan $ExpiryDate = (Get-Date).AddYears(2).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") $PasswordCred = Add-MgApplicationPassword -ApplicationId $Application.Id -BodyParameter @{ passwordCredential = @{ displayName = "MigrationToolSecret" endDateTime = $ExpiryDate } } # --- OUTPUT --- Write-Host "`n-------------------------------------------------------" -ForegroundColor Yellow Write-Host " SETUP COMPLETE - SAVE THESE DETAILS" -ForegroundColor Yellow Write-Host "-------------------------------------------------------" -ForegroundColor Yellow Write-Host "Application Name : $AppName" Write-Host "Application (Client) ID : $($Application.AppId)" Write-Host "Client Secret Value : $($PasswordCred.SecretText)" Write-Host "Directory (Tenant) ID : $TenantId" Write-Warning "IMPORTANT: Copy the Client Secret Value immediately." } catch { Write-Error "Operation failed: $_" } # --- FINAL DISCONNECT --- Disconnect-MgGraph Read-Host "`nPress Enter to close this window"
- חשוב לשמור את פרטי הכניסה הבאים במקום בטוח. אם פרטי הכניסה ידלפו, האקרים יוכלו לגשת לכל הנתונים שלכם ב-Exchange Online.
- סוד לקוח
- מזהה האפליקציה (אפליקציית הלקוח)
- מזהה הספרייה (הדייר)
אפשרות 2: שימוש ב-Windows PowerShell
- ב-Windows, יוצרים קובץ טקסט פשוט חדש בשם migration_app_creator.ps1.
- מעתיקים את בלוק הקוד שלמטה, מדביקים אותו בקובץ החדש ולוחצים על Run with Powershell (הפעלה באמצעות Powershell).
- חשוב לשמור את פרטי הכניסה הבאים במקום בטוח. אם פרטי הכניסה ידלפו, האקרים יוכלו לגשת לכל הנתונים שלכם ב-Exchange Online.
- סוד לקוח
- מזהה האפליקציה (אפליקציית הלקוח)
- מזהה הספרייה (הדייר)
<# .SYNOPSIS Automates the creation of a Single-Tenant Entra ID App for Workspace Migration. Strictly forces account selection and verifies specific Admin roles. #> # Check if the module is missing if (-not (Get-Module -ListAvailable -Name Microsoft.Graph.Authentication)) { Write-Host "Microsoft Graph module is NOT installed." -ForegroundColor Yellow $UserResponse = Read-Host "Would you like to try installing Microsoft Graph? (Y/N)" if ($UserResponse -ieq "Y") { try { # Use only native cmdlets, no .NET property setting Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force -AllowClobber Write-Host "Installation complete!" -ForegroundColor Green } catch { Write-Error "Policy is blocking installation. Please contact IT to install Microsoft.Graph module." Read-Host "Press Enter to exit"; exit } } else { exit } } else { Write-Host "Microsoft Graph modules detected. Proceeding..." -ForegroundColor Green } # --- STEP 0: THE "DEEP" LOGOUT --- Write-Host "Forcing session cleanup..." -ForegroundColor Gray Disconnect-MgGraph -ErrorAction SilentlyContinue # Force clear the local token cache folder if it exists $CachePath = "$env:USERPROFILE\.mg" if (Test-Path $CachePath) { try { Remove-Item $CachePath -Recurse -Force -ErrorAction SilentlyContinue } catch {} } Write-Host "Opening Microsoft Login... (Please select the correct account)" -ForegroundColor Cyan $RequiredScopes = @( "Application.ReadWrite.All", "AppRoleAssignment.ReadWrite.All", "Directory.Read.All", "RoleManagement.Read.Directory" ) try { # In v2, -ContextScope Process is the most reliable way to force account selection # and prevent the session from saving to the machine permanently. Connect-MgGraph -Scopes $RequiredScopes -ContextScope Process $Context = Get-MgContext if ($null -eq $Context) { throw "Login was cancelled or failed." } $UserPrincipal = $Context.Account Write-Host "Logged in as: $UserPrincipal" -ForegroundColor Green # --- ROLE VALIDATION --- Write-Host "Verifying Directory Roles..." -ForegroundColor Gray $UserRoles = Get-MgUserMemberOf -UserId $Context.Account -All | Where-Object { $_.AdditionalProperties.displayName -ne $null } $Authorized = $false $RequiredRoles = @("Global Administrator", "Privileged Role Administrator") foreach ($role in $UserRoles) { $roleName = $role.AdditionalProperties.displayName if ($roleName -in $RequiredRoles) { $Authorized = $true Write-Host "Access Granted: $roleName" -ForegroundColor Green break } } if (-not $Authorized) { Write-Host "`nCRITICAL ERROR: Insufficient Privileges." -ForegroundColor Red Write-Host "Account must be 'Global Administrator' or 'Privileged Role Administrator'." -ForegroundColor Yellow Disconnect-MgGraph Read-Host "`nPress Enter to exit"; exit } } catch { Write-Error "Login failed: $_" Read-Host "Press Enter to exit"; exit } # --- USER INPUT --- Write-Host "`n--- APPLICATION SETUP ---" -ForegroundColor Cyan $InputName = Read-Host "Enter the name for your new Entra ID Application (Default: Workspace Migration App)" $AppName = if ([string]::IsNullOrWhiteSpace($InputName)) { "Workspace Migration App" } else { $InputName } # --- CONFIGURATION --- $PermissionMap = @{ "calendar.read" = "Calendars.Read" "mail.read" = "Mail.Read" "contacts.read" = "Contacts.Read" "directory.read" = "Directory.Read.All" } $TenantId = $Context.TenantId $GraphAppId = "00000003-0000-0000-c000-000000000000" try { # --- STEP 1: REGISTER APPLICATION --- Write-Host "Creating Application: $AppName..." -ForegroundColor Cyan $Application = New-MgApplication -BodyParameter @{ displayName = $AppName signInAudience = "AzureADMyOrg" } # --- STEP 2: PREPARE SERVICE PRINCIPAL --- $NewServicePrincipal = New-MgServicePrincipal -BodyParameter @{ appId = $Application.AppId } Write-Host "Waiting 10 seconds for replication..." -ForegroundColor DarkGray Start-Sleep -Seconds 10 # --- STEP 3: CONFIGURE & GRANT PERMISSIONS --- Write-Host "Configuring API Permissions & Granting Admin Consent..." -ForegroundColor Cyan $GraphSP = Get-MgServicePrincipal -Filter "AppId eq '$GraphAppId'" | Select-Object -First 1 $ResourceAccessList = @() foreach ($key in $PermissionMap.Keys) { $RealRoleName = $PermissionMap[$key] $Role = $GraphSP.AppRoles | Where-Object { $_.Value -eq $RealRoleName } if ($Role) { $ResourceAccessList += @{ id = $Role.Id; type = "Role" } New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $NewServicePrincipal.Id -BodyParameter @{ principalId = $NewServicePrincipal.Id resourceId = $GraphSP.Id appRoleId = $Role.Id } | Out-Null Write-Host " - Granted: $RealRoleName" -ForegroundColor Gray } } Update-MgApplication -ApplicationId $Application.Id -RequiredResourceAccess @(@{ resourceAppId = $GraphAppId resourceAccess = $ResourceAccessList }) # --- STEP 4: CREATE CLIENT SECRET --- Write-Host "Generating Client Secret..." -ForegroundColor Cyan $ExpiryDate = (Get-Date).AddYears(2).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") $PasswordCred = Add-MgApplicationPassword -ApplicationId $Application.Id -BodyParameter @{ passwordCredential = @{ displayName = "MigrationToolSecret" endDateTime = $ExpiryDate } } # --- OUTPUT --- Write-Host "`n-------------------------------------------------------" -ForegroundColor Yellow Write-Host " SETUP COMPLETE - SAVE THESE DETAILS" -ForegroundColor Yellow Write-Host "-------------------------------------------------------" -ForegroundColor Yellow Write-Host "Application Name : $AppName" Write-Host "Application (Client) ID : $($Application.AppId)" Write-Host "Client Secret Value : $($PasswordCred.SecretText)" Write-Host "Directory (Tenant) ID : $TenantId" Write-Warning "IMPORTANT: Copy the Client Secret Value immediately." } catch { Write-Error "Operation failed: $_" } # --- FINAL DISCONNECT --- Disconnect-MgGraph Read-Host "`nPress Enter to close this window"
שימוש ב-Azure AD להגדרת חיבור ידני
השלבים הספציפיים של מיקרוסופט עשויים להשתנות בהתאם לגרסה של פורטל Azure ולעדכונים שמיקרוסופט מבצעת. לקבלת ההנחיות העדכניות בנושא רישום והרשאה של אפליקציות, אפשר לעיין במסמכי התיעוד של מיקרוסופט.
שלב 1: רישום אפליקציה חדשה
מטעמי אבטחה, מומלץ לרשום את האפליקציה החדשה כדייר יחיד.
- נכנסים ל-Microsoft Azure Portal בתור אדמין.
- ב-Azure Active Directory (Azure AD), עוברים אל App registrations.
- לוחצים על New Registration (הרשמה חדשה) ומזינים שם לאפליקציה (לדוגמה, Enterprise Migration App).
- בקטע סוגי חשבונות נתמכים, לוחצים על חשבונות רק בספרייה הארגונית הזו כדי ליצור אפליקציה עם דייר יחיד.
- לוחצים על הרשמה.
שלב 2: הגדרת הרשאות API
בחר אחת מהאפשרויות הבאות:
אפשרות 1: הוספת הרשאות באופן ידני
- בחלונית הניווט הימנית, בקטע ניהול, לוחצים על הרשאות API.
- לוחצים על Add a permission (הוספת הרשאה)
Microsoft APIs (ממשקי API של מיקרוסופט)
Microsoft Graph (מיקרוסופט גרף).
- בקטע הרשאות לאפליקציה, בוחרים:
- calendars.read
- mail.read
- contacts.read
- Directory.read.all
- לוחצים על Grant admin consent for [Your organization] (מתן הסכמת אדמין ל[שם הארגון]).
אפשרות 2: עריכת המניפסט של האפליקציה
- פותחים את קובץ המניפסט של האפליקציה.
- בשורה “resourceAccess” : [ ], מעתיקים ומדביקים את בלוק הקוד שלמטה.
אם ל-“resourceAccess” : [ ] כבר יש ערך, מוסיפים פסיק ואז מדביקים את בלוק הקוד.
{ "id": "089fe4d0-434a-44c5-8827-41ba8a0b17f5", "type": "Role" }, { "id": "810c84a8-4a9e-49e6-bf7d-12d183f40d01", "type": "Role" }, { "id": "7ab1d382-f21e-4acd-a863-ba3e13f7da61", "type": "Role" }, { "id": "798ee544-9d2d-430c-a058-570e29e34338", "type": "Role" } - לוחצים על Grant admin consent for [Your organization] (מתן הסכמת אדמין ל[שם הארגון]).
שלב 3: יצירת סוד לקוח
- בניווט הימני, בקטע Manage, לוחצים על Certificates & secrets
New client secret.
- מזינים תיאור, בוחרים תקופת תפוגה ולוחצים על הוספה.
- מעתיקים את ערך סוד הלקוח ומאחסנים אותו באופן מאובטח. הערך מוצג רק פעם אחת.
שלב 4: אוספים את פרטי הכניסה של האפליקציה
לוחצים על Overview ורושמים בצורה מאובטחת את פרטי הכניסה הבאים:
- מזהה האפליקציה (אפליקציית הלקוח)
- מזהה הספרייה (הדייר)
Google, Google Workspace וסימנים וסמלי לוגו קשורים הם סימנים מסחריים של Google LLC. כל שמות החברות והמוצרים האחרים הם סימנים מסחריים של החברות שאליהן הם משויכים.