다음 단계에 따라 Azure 포털에서 Microsoft Azure 애플리케이션을 만드세요. 고급 데이터 가져오기 방법을 사용하여 OneDrive 또는 SharePoint Online (Microsoft 365) 데이터를 Google Workspace 계정으로 복사하는 경우 안전한 데이터 가져오기를 위해 Azure 애플리케이션이 필요합니다. 다음 두 가지 방법 중 하나를 선택할 수 있습니다.
PowerShell 스크립트를 사용하여 자동 연결 설정하기
이 단계를 완료하려면 전역 관리자 또는 권한이 있는 역할 관리자여야 합니다.
옵션 1: Azure Cloud Shell 사용
- 관리자로 Azure 포털에 로그인합니다.
- Cloud Shell
Powershell을 클릭합니다.
- 메시지가 표시되면 스토리지 계정을 만들고 기본 설정을 수락합니다.
- 애플리케이션을 만들려면 다음 명령어를 입력하고 Enter를 클릭합니다.
Install-Module Microsoft.Graph -Scope CurrentUser
- 신뢰할 수 없는 저장소에서 설치하라는 메시지가 표시되면 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 Data Import App)" $AppName = if ([string]::IsNullOrWhiteSpace($InputName)) { "Workspace Data Import 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"
- 다음 사용자 인증 정보를 기록하고 안전하게 저장합니다. 사용자 인증 정보가 유출되면 해커가 모든 OneDrive 또는 SharePoint Online 데이터에 액세스할 수 있습니다.
- 클라이언트 보안 비밀번호
- 애플리케이션(클라이언트) ID
- 디렉터리(테넌트) ID
옵션 2: Windows PowerShell 사용
- Windows에서 새 일반 텍스트 파일을 만들고 이름을 migration_app_creator.ps1로 지정합니다.
- 다음 코드 블록을 복사하여 새 파일에 붙여넣고 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 Data Import App)" $AppName = if ([string]::IsNullOrWhiteSpace($InputName)) { "Workspace Data Import 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"
- 다음 사용자 인증 정보를 기록하고 안전하게 저장합니다. 사용자 인증 정보가 유출되면 해커가 모든 OneDrive 또는 SharePoint Online 데이터에 액세스할 수 있습니다.
- 클라이언트 보안 비밀번호
- 애플리케이션(클라이언트) ID
- 디렉터리(테넌트) ID
Microsoft Azure를 사용하여 수동 연결 설정
구체적인 Microsoft 단계는 Azure 포털 버전 및 Microsoft에서 적용한 업데이트에 따라 다를 수 있습니다. 앱 등록 및 승인에 관한 최신 안내는 Microsoft 문서를 참고하세요.
1단계: 새 애플리케이션 등록하기
- 관리자로 Azure 포털에 로그인합니다.
- Azure 서비스에서 앱 등록으로 이동합니다.
- 새 등록을 클릭하고 애플리케이션 이름 (예: 고급 가져오기 앱)을 입력합니다.
- 지원되는 계정 유형에서 이 조직 디렉터리의 계정만을 클릭하여 단일 테넌트 애플리케이션을 만듭니다.
- 등록을 클릭합니다.
2단계: API 권한 구성하기
다음 옵션 중 하나를 선택합니다.
옵션 1: 권한 수동으로 추가
- 측면의 관리 섹션에서 API 권한을 클릭합니다.
- 권한 추가를 클릭하고 Microsoft API 탭에서 Sharepoint를 클릭합니다.
- 애플리케이션 권한을 클릭하고 사이트 드롭다운 메뉴에서 Sites.FullControl.All 체크박스를 선택합니다.
- 권한 추가를 클릭합니다.
- 권한 추가로 돌아가서 Microsoft Graph를 선택합니다.
- 애플리케이션 권한을 클릭하고 다음 권한을 부여합니다.
- LicenseAssignment.Read.All
- Application.Read.All
- 권한 추가를 클릭합니다.
- 조직에 대해 관리자의 동의 제출을 클릭하여 애플리케이션에 데이터 액세스 권한이 있는지 확인합니다.
옵션 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단계: 클라이언트 보안 비밀번호 생성
- 측면의 관리에서 인증서 및 보안 비밀
새 클라이언트 보안 비밀번호를 클릭합니다.
- 설명을 입력하고 만료 기간을 선택한 다음 추가를 클릭합니다.
- 클라이언트 보안 비밀번호 값을 복사하여 안전하게 저장합니다. 값은 한 번만 표시됩니다.
4단계: 애플리케이션 사용자 인증 정보 수집하기
중요: 애플리케이션 사용자 인증 정보를 안전하게 저장하세요. 사용자 인증 정보가 유출되면 해커가 모든 OneDrive 또는 SharePoint Online 데이터에 액세스할 수 있습니다.
개요를 클릭하고 다음 사용자 인증 정보를 안전하게 기록합니다.
- 애플리케이션(클라이언트) ID
- 디렉터리(테넌트) ID
Google, Google Workspace 및 관련 마크와 로고는 Google LLC의 상표입니다. 기타 모든 회사명 및 제품명은 해당 업체의 상표입니다.