Hãy làm theo các bước sau để tạo ứng dụng Microsoft Azure trong cổng thông tin Azure, hỗ trợ di chuyển dữ liệu an toàn từ Exchange Online (Microsoft 365) sang tài khoản Google Workspace của bạn. Bạn có thể chọn một trong hai phương thức:
- Sử dụng tập lệnh PowerShell để thiết lập kết nối tự động
- Sử dụng Azure AD để thiết lập kết nối thủ công
Sử dụng tập lệnh PowerShell để thiết lập kết nối tự động
Bạn phải là quản trị viên có vai trò toàn cầu hoặc vai trò đặc quyền để hoàn tất các bước này.
Trước khi bắt đầu: Bạn phải cài đặt Install-Module Microsoft.Graph -Scope CurrentUser.
Cách 1: Sử dụng Azure Cloud Shell
- Với tư cách quản trị viên, hãy đăng nhập vào cổng thông tin Microsoft Azure.
- Nhấp vào Cloud Shell
Powershell.
- Nếu được nhắc, hãy tạo một tài khoản lưu trữ và chấp nhận các chế độ cài đặt mặc định.
- Dán lệnh Install-Module Microsoft.Graph -Scope CurrentUser rồi nhấp vào Enter.
- Nếu bạn thấy lời nhắc cài đặt từ Kho lưu trữ không đáng tin cậy, hãy nhập Y rồi nhấp vào Enter.
- Sao chép khối mã bên dưới, dán vào PowerShell rồi nhấp vào 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"
- Ghi lại thông tin đăng nhập sau đây và lưu trữ thông tin đó một cách an toàn. Nếu thông tin đăng nhập bị rò rỉ, tin tặc có thể truy cập vào tất cả dữ liệu Exchange Online của bạn.
- Mật khẩu ứng dụng
- Mã ứng dụng (ứng dụng khách)
- Mã thư mục (máy thuê)
Cách 2: Sử dụng Windows PowerShell
- Trong Windows, hãy tạo một tệp văn bản thuần tuý mới có tên là migration_app_creator.ps1.
- Sao chép khối mã bên dưới, dán vào tệp mới rồi nhấp vào Run with Powershell (Chạy bằng Powershell).
- Ghi lại thông tin đăng nhập sau đây và lưu trữ thông tin đó một cách an toàn. Nếu thông tin đăng nhập bị rò rỉ, tin tặc có thể truy cập vào tất cả dữ liệu Exchange Online của bạn.
- Mật khẩu ứng dụng
- Mã ứng dụng (ứng dụng khách)
- Mã thư mục (máy thuê)
<# .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"
Sử dụng Azure AD để thiết lập kết nối thủ công
Các bước cụ thể của Microsoft có thể khác nhau tuỳ thuộc vào phiên bản cổng thông tin Azure và các bản cập nhật do Microsoft thực hiện. Hãy tham khảo tài liệu của Microsoft để biết hướng dẫn mới nhất về việc đăng ký và uỷ quyền cho ứng dụng.
Bước 1: Đăng ký ứng dụng mới
Vì lý do bảo mật, bạn nên đăng ký ứng dụng mới dưới dạng một máy thuê.
- Với tư cách quản trị viên, hãy đăng nhập vào cổng thông tin Microsoft Azure.
- Trong Azure Active Directory (Azure AD), hãy chuyển đến App registrations (Đăng ký ứng dụng).
- Nhấp vào New Registration (Đăng ký mới) rồi nhập tên cho ứng dụng của bạn (ví dụ: Enterprise Migration App).
- Đối với Supported account types (Các loại tài khoản được hỗ trợ), hãy nhấp vào Accounts in this organizational directory only (Chỉ các tài khoản trong thư mục tổ chức này) để tạo ứng dụng một máy thuê.
- Nhấp vào Register (Đăng ký).
Bước 2: Định cấu hình quyền API
Chọn một trong các tùy chọn bên dưới:
Cách 1: Thêm quyền theo cách thủ công
- Trong bảng điều hướng bên trái, đối với Manage (Quản lý), hãy nhấp vào API permissions (Quyền API).
- Nhấp vào Add a permission (Thêm quyền)
Microsoft APIs (API của Microsoft)
Microsoft Graph.
- Đối với application permissions (quyền ứng dụng), hãy chọn:
- calendars.read
- mail.read
- contacts.read
- Directory.read.all
- Nhấp vào Grant admin consent for [Your organization] (Cấp quyền đồng ý của quản trị viên cho [Tổ chức của bạn]).
Cách 2: Chỉnh sửa tệp kê khai ứng dụng
- Mở tệp kê khai ứng dụng.
- Đối với “resourceAccess” : [ ], hãy sao chép và dán khối mã bên dưới.
Nếu “resourceAccess” : [ ] đã có giá trị, hãy thêm dấu phẩy rồi dán khối mã.
{ "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" } - Nhấp vào Grant admin consent for [Your organization] (Cấp quyền đồng ý của quản trị viên cho [Tổ chức của bạn]).
Bước 3: Tạo mật khẩu ứng dụng
- Trong bảng điều hướng bên trái, đối với Manage (Quản lý), hãy nhấp vào Certificates & secrets (Chứng chỉ và khoá bí mật)
New client secret (Khoá bí mật ứng dụng mới).
- Nhập nội dung mô tả, chọn thời gian hết hạn rồi nhấp vào Add (Thêm).
- Sao chép Client secret value (Giá trị mật khẩu ứng dụng) và lưu trữ thông tin đó một cách an toàn. Giá trị này chỉ hiển thị một lần.
Bước 4: Thu thập thông tin đăng nhập ứng dụng
Nhấp vào Overview (Tổng quan) rồi ghi lại thông tin đăng nhập sau đây một cách an toàn:
- Mã ứng dụng (ứng dụng khách)
- Mã thư mục (máy thuê)
Google, Google Workspace và những nhãn hiệu cũng như biểu tượng có liên quan là nhãn hiệu của Google LLC. Tất cả các tên sản phẩm và công ty khác là nhãn hiệu của những công ty mà chúng liên kết.