إعداد تطبيق Azure لخدمة OneDrive

اتّبِع الخطوات التالية لإنشاء تطبيق Microsoft Azure في بوابة Azure. إذا كنت تستخدم طريقة استيراد البيانات المتقدّمة لنسخ بيانات OneDrive إلى حسابات Google Workspace، ستحتاج إلى تطبيق Azure لضمان استيراد البيانات بأمان. يمكنك اختيار إحدى الطريقتَين التاليتَين:

استخدام نص PowerShell البرمجي لإعداد اتصال تلقائي

يجب أن تكون مشرفًا ذا دور عالمي أو دور مميّز لإكمال هذه الخطوات.

الخيار 1: استخدام Azure Cloud Shell

  1. بصفتك مشرفًا، سجِّل الدخول إلى بوابة Azure.
  2. انقر على Cloud Shell ثم ‫PowerShell.
  3. إذا طُلب منك ذلك، أنشِئ حساب تخزين واقبل الإعدادات التلقائية.
  4. لإنشاء التطبيق، أدخِل الأمر التالي ثم انقر على مفتاح الإدخال:

    Install-Module Microsoft.Graph -Scope CurrentUser

  5. إذا ظهرت لك رسالة تطلب منك التثبيت من مستودع غير موثوق به، أدخِل Y ثم انقر على مفتاح الإدخال.
  6. انسخ مجموعة الرموز التالية والصقها في PowerShell، ثم انقر على مفتاح الإدخال.
    <#    
    .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 ---
    # Updated Map containing only the requested Graph permissions
    $PermissionMap = @{
        "licenseassignment.read.all"  = "LicenseAssignment.Read.All"     
        "application.read.all"        = "Application.Read.All"
    }
    
    $TenantId = $Context.TenantId
    $GraphAppId = "00000003-0000-0000-c000-000000000000"
    $SpoAppId   = "00000003-0000-0ff1-ce00-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
        
        # 1. Process Microsoft Graph Permissions
        $GraphSP = Get-MgServicePrincipal -Filter "AppId eq '$GraphAppId'" | Select-Object -First 1
        $GraphResourceAccessList = @()
    
        foreach ($key in $PermissionMap.Keys) {
            $RealRoleName = $PermissionMap[$key]
            $Role = $GraphSP.AppRoles | Where-Object { $_.Value -eq $RealRoleName }
    
            if ($Role) {
                $GraphResourceAccessList += @{ 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 (Graph): $RealRoleName" -ForegroundColor Gray
            }
        }
    
        # 2. Process SharePoint Online Permissions
        $SpoSP = Get-MgServicePrincipal -Filter "AppId eq '$SpoAppId'" | Select-Object -First 1
        $SpoResourceAccessList = @()
        $SpoRole = $SpoSP.AppRoles | Where-Object { $_.Value -eq "Sites.FullControl.All" }
    
        if ($SpoRole) {
            $SpoResourceAccessList += @{ id = $SpoRole.Id; type = "Role" }
    
            New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $NewServicePrincipal.Id -BodyParameter @{
                principalId = $NewServicePrincipal.Id
                resourceId  = $SpoSP.Id
                appRoleId   = $SpoRole.Id
            } | Out-Null
            Write-Host " - Granted (SharePoint): Sites.FullControl.All" -ForegroundColor Gray
        }
    
        Update-MgApplication -ApplicationId $Application.Id -RequiredResourceAccess @(
            @{ resourceAppId = $GraphAppId; resourceAccess = $GraphResourceAccessList },
            @{ resourceAppId = $SpoAppId; resourceAccess = $SpoResourceAccessList }
        )
    
        # --- 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"
    
       
  7. دوِّن بيانات الاعتماد التالية وخزِّنها بأمان. وفي حال تسريب بيانات الاعتماد، سيتمكن المخترقون من الوصول إلى جميع بيانات OneDrive.
    • سر العميل
    • معرّف التطبيق (العميل)
    • معرّف الدليل (المستأجر)

الخيار 2: استخدام Windows PowerShell

  1. في Windows، أنشِئ ملفًا جديدًا بنص عادي وسمِّه migration_app_creator.ps1.
  2. انسخ مجموعة الرموز التالية والصقها في الملف الجديد، ثم انقر على التشغيل باستخدام PowerShell.
     <#
        .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 ---
    # Application Permissions mapped to their respective API App IDs
    $ApiConfigurations = @{
        "00000003-0000-0000-c000-000000000000" = @("LicenseAssignment.Read.All", "Application.Read.All") # Microsoft Graph
        "00000003-0000-0ff1-ce00-000000000000" = @("Sites.FullControl.All")                              # SharePoint Online
    }
    
    $TenantId = $Context.TenantId
    
    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
        
        $RequiredResourceAccess = @()
    
        foreach ($ApiAppId in $ApiConfigurations.Keys) {
            $ApiSP = Get-MgServicePrincipal -Filter "AppId eq '$ApiAppId'" | Select-Object -First 1
            $ResourceAccessList = @()
            
            foreach ($RoleName in $ApiConfigurations[$ApiAppId]) {
                $Role = $ApiSP.AppRoles | Where-Object { $_.Value -eq $RoleName }
                
                if ($Role) {
                    $ResourceAccessList += @{ id = $Role.Id; type = "Role" }
                    
                    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $NewServicePrincipal.Id -BodyParameter @{
                        principalId = $NewServicePrincipal.Id
                        resourceId  = $ApiSP.Id
                        appRoleId   = $Role.Id
                    } | Out-Null
                    Write-Host " - Granted: $RoleName" -ForegroundColor Gray
                }
            }
            
            if ($ResourceAccessList.Count -gt 0) {
                $RequiredResourceAccess += @{
                    resourceAppId  = $ApiAppId
                    resourceAccess = $ResourceAccessList
                }
            }
        }
    
        Update-MgApplication -ApplicationId $Application.Id -RequiredResourceAccess $RequiredResourceAccess
    
        # --- 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"
    
       
  3. دوِّن بيانات الاعتماد التالية وخزِّنها بأمان. وفي حال تسريب بيانات الاعتماد، سيتمكن المخترقون من الوصول إلى جميع بيانات OneDrive.
    • سر العميل
    • معرّف التطبيق (العميل)
    • معرّف الدليل (المستأجر)

استخدام Microsoft Azure لإعداد اتصال يدوي

قد تختلف خطوات Microsoft المحدّدة حسب إصدار بوابة Azure والتحديثات التي أجرتها Microsoft. يُرجى الرجوع إلى مستندات Microsoft للحصول على أحدث الإرشادات حول تسجيل التطبيقات والتفويض.

الخطوة 1: تسجيل تطبيق جديد

  1. بصفتك مشرفًا، سجِّل الدخول إلى بوابة Azure.
  2. في "خدمات Azure"، انتقِل إلى تسجيل التطبيقات.
  3. انقر على تسجيل جديد وأدخِل اسمًا لتطبيقك (مثل تطبيق الاستيراد المتقدّم).
  4. بالنسبة إلى أنواع الحسابات المتوافقة، انقر على الحسابات في هذا الدليل التنظيمي فقط لإنشاء تطبيق مستأجر واحد.
  5. انقر على تسجيل.

الخطوة 2: ضبط أذونات واجهة برمجة التطبيقات

حدّد أحد الخيارات التالية:

الخيار 1: إضافة الأذونات يدويًا

  1. على الجانب، في قسم إدارة ، انقر على أذونات واجهة برمجة التطبيقات.
  2. انقر على إضافة إذن وفي علامة التبويب واجهات برمجة التطبيقات من Microsoft ، انقر على Sharepoint.
  3. انقر على أذونات التطبيق وضَع علامة في المربّع Sites.FullControl.All في القائمة المنسدلة "المواقع الإلكترونية".
  4. انقر على إضافة إذن.
  5. ارجِع إلى إضافة إذن وانقر على Microsoft Graph.
  6. انقر على "أذونات التطبيق" وامنح الأذونات التالية:
    • LicenseAssignment.Read.All
    • Application.Read.All
  7. انقر على إضافة إذن.
  8. انقر على منح موافقة المشرف إلى مؤسستك لضمان حصول التطبيق على إذن الوصول إلى البيانات.

الخيار 2: تعديل بيان التطبيق

  1. افتح بيان التطبيق.
  2. انتقِل إلى “resourceAccess” : [ ] وحدِّد أحد الخيارات:
    • إذا كانت “resourceAccess” : [ ] تتضمّن قيمة، أضِف فاصلة ثم الصِق مجموعة الرموز التالية.
    • إذا كانت “resourceAccess” : [ ] لا تتضمّن قيمة، انسخ مجموعة الرموز التالية والصقها.
         "requiredResourceAccess": [
          {
              "resourceAppId": "00000003-0000-0000-c000-000000000000",
              "resourceAccess": [
                  {
                      "id": "e2f98668-2877-4f38-a2f4-8202e0717aa1",
                      "type": "Role"
                  },
                  {
                      "id": "9a5d68dd-52b0-4cc2-bd40-abcf44ac3a30",
                      "type": "Role"
                  }
              ]
          },
          {
              "resourceAppId": "00000003-0000-0ff1-ce00-000000000000",
              "resourceAccess": [
                  {
                      "id": "678536fe-1083-478a-9c59-b99265e6b0d3",
                      "type": "Role"
                  }
              ]
          }
      ]
         
  3. انقر على منح موافقة المشرف إلى مؤسستك.

الخطوة 3: إنشاء سر العميل

  1. على الجانب، في قسم إدارة ، انقر على الشهادات والأسرار ثم سر عميل جديد.
  2. أدخِل وصفًا واختَر فترة انتهاء صلاحية، ثم انقر على إضافة.
  3. انسخ قيمة سر العميل وخزِّنها بأمان. يُرجى العلم أنّ القيمة تعرض مرة واحدة فقط.

الخطوة 4: جمع بيانات اعتماد التطبيق

ملاحظة مهمة: يجب تخزين بيانات اعتماد التطبيق بأمان. وفي حال تسريب بيانات الاعتماد، سيتمكن المخترقون من الوصول إلى جميع بيانات OneDrive.

انقر على نظرة عامة ودوِّن بيانات الاعتماد التالية بأمان:

  • معرّف التطبيق (العميل)
  • معرّف الدليل (المستأجر)


إنّ Google وGoogle Workspace والعلامات والشعارات ذات الصلة هي علامات تجارية (TM) تابعة لشركة Google LLC. وجميع أسماء الشركات والمنتجات الأخرى هي علامات تجارية (TM) تملكها الشركات ذات الصلة بها.