(この記事はClaude Sonnet 4により執筆しています)
はじめに
SharePoint Onlineを使っていると、気がつけばサイトが増えて権限管理が複雑になっていませんか?
「あのサイトには誰がアクセスできるんだっけ?」 「外部ユーザーに権限を与えすぎていないか確認したい」 「コンプライアンス監査のために権限一覧が必要」
そんな悩みを解決するために、SharePoint Onlineテナント内のすべてのサイト権限を一括で取得し、CSV形式で出力するPowerShellスクリプトを開発しました。
今回は、このツールの使い方と、開発中に遭遇したPnP.PowerShellモジュールのつまづきポイントとその解決策をご紹介します。
🎯 このツールでできること
主な機能
- 全サイト権限監査: テナント内すべてのサイト(チームサイト、コミュニケーションサイト、OneDrive等)の権限設定を自動収集
- 詳細情報取得: ユーザー名、ログイン名、メールアドレス、割り当てロールを包括的に取得
- CSV出力: Excel等での分析に適したフォーマットで結果をエクスポート
- 視覚的確認: Out-GridViewによる結果の即座確認
出力例
SiteUrl,Principal,LoginName,Email,Roles https://contoso.sharepoint.com/sites/sales,田中太郎,i:0#.f|membership|tanaka@contoso.com,tanaka@contoso.com,編集 https://contoso.sharepoint.com/sites/sales,営業チーム,c:0o.c|federateddirectoryclaimprovider|abc123...,,"フル コントロール" https://contoso.sharepoint.com/sites/hr,人事部グループ,c:0o.c|federateddirectoryclaimprovider|def456...,,編集
🚀 使い方
前提条件
このツールを使用する前に、以下の環境準備が必要です:
1. PowerShell 7.x のインストール
最新のPnP.PowerShellモジュールはPowerShell 7.x以上が必要です:
# PowerShellのバージョン確認 $PSVersionTable.PSVersion
PowerShell 7.xがインストールされていない場合:
- PowerShell 7.x 公式ダウンロードページ からダウンロード
- Windows PowerShell(5.1)では最新のPnP.PowerShellは動作しません
2. Visual Studio Code のインストール
PowerShell 7.xではPowerShell ISEが使用できないため、VS Codeの使用を強く推奨します:
- Visual Studio Code をダウンロード・インストール
- PowerShell拡張機能をインストール(
ms-vscode.powershell
)
VS Codeでの推奨設定:
{ "powershell.powerShellDefaultVersion": "PowerShell (x64)", "terminal.integrated.defaultProfile.windows": "PowerShell" }
📄 スクリプト全文
実際に使用するスクリプトファイルの全文をご紹介します。以下のコードをコピーして使用してください。
SPO-Setup.ps1(初回セットアップ用)
# SharePoint Online 初回セットアップスクリプト # このスクリプトは初回のみ実行してください Write-Host "SharePoint Online 初回セットアップを開始します..." -ForegroundColor Green # テナントの設定(環境に合わせて変更してください) $TenantName = "your-tenant.onmicrosoft.com" $TenantUrl = "https://your-tenant.sharepoint.com" # アプリケーションの設定(任意のアプリ名とパスワードに変更してください) $ApplicationName = "sharepoint-client-ps" $CertificatePassword = "YourSecurePassword123!" # パスワードをSecureStringに変換 $SecureCertPassword = ConvertTo-SecureString -String $CertificatePassword -AsPlainText -Force # 設定ファイルのパス $configPath = ".\SharePointOnlineClientConfig.json" Write-Host "1. PnP.PowerShellモジュールをインストールしています..." -ForegroundColor Yellow # モジュールインストール(初回のみ) if (!(Get-Module -ListAvailable -Name "PnP.PowerShell")) { Write-Host "PnP.PowerShellモジュールが見つかりません。インストールします..." -ForegroundColor Yellow Install-Module -Name "PnP.PowerShell" -Force -AllowClobber Write-Host "PnP.PowerShellモジュールのインストールが完了しました。" -ForegroundColor Green } else { Write-Host "PnP.PowerShellモジュールは既にインストールされています。" -ForegroundColor Green } # モジュール読み込み Import-Module -Name "PnP.PowerShell" Write-Host "2. Entra IDアプリケーションと証明書を生成しています..." -ForegroundColor Yellow # 証明書とEntraIDアプリを生成 try { $appInfo = Register-PnPEntraIDApp -ApplicationName $ApplicationName -Tenant $TenantName -CertificatePassword $SecureCertPassword -Store CurrentUser Write-Host "Entra IDアプリケーションと証明書の生成が完了しました!" -ForegroundColor Green Write-Host "以下の情報をメインスクリプトに設定してください:" -ForegroundColor Cyan Write-Host "ClientID: $($appInfo.ClientId)" -ForegroundColor White Write-Host "証明書パス: $($appInfo.CertificatePath)" -ForegroundColor White # 設定ファイルに情報を保存 $config = @{ TenantName = $TenantName TenantUrl = $TenantUrl ClientID = $appInfo.'AzureAppId/ClientId' CertificatePath = $appInfo.'Pfx file' ApplicationName = $ApplicationName CertificatePassword = $CertificatePassword SetupDate = Get-Date } $config | ConvertTo-Json -Depth 3 | Out-File -FilePath $configPath -Encoding UTF8 Write-Host "設定情報を $configPath に保存しました。" -ForegroundColor Green } catch { Write-Error "Entra IDアプリケーションの生成に失敗しました: $_" exit 1 } Write-Host "初回セットアップが完了しました!" -ForegroundColor Green Write-Host "次回からは 'SPO-PermissionAudit.ps1' を実行してください。" -ForegroundColor Cyan
SPO-PermissionAudit.ps1(メイン実行用)
# SharePoint Online 全サイト権限リストアップスクリプト # 事前に 'SPO-Setup.ps1' を実行してください Write-Host "SharePoint Online 全サイト権限リストアップを開始します..." -ForegroundColor Green # 設定ファイルから情報を読み込み $configPath = ".\SharePointOnlineClientConfig.json" if (!(Test-Path $configPath)) { Write-Error "設定ファイルが見つかりません: $configPath" Write-Host "先に 'SPO-Setup.ps1' を実行してください。" -ForegroundColor Yellow exit 1 } try { $config = Get-Content -Path $configPath -Encoding UTF8 | ConvertFrom-Json $TenantName = $config.TenantName $TenantUrl = $config.TenantUrl $ClientID = $config.ClientID $CertificatePath = $config.CertificatePath $CertificatePassword = $config.CertificatePassword Write-Host "設定ファイルから情報を読み込みました。" -ForegroundColor Green } catch { Write-Error "設定ファイルの読み込みに失敗しました: $_" exit 1 } # 出力先のCSVファイルパス $OutputCsvPath = "AllSitePermissions.csv" # パスワードをSecureStringに変換 $SecureCertPassword = ConvertTo-SecureString -String $CertificatePassword -AsPlainText -Force # モジュール読み込み if (!(Get-Module -Name "PnP.PowerShell")) { Import-Module -Name "PnP.PowerShell" } # テナントに接続 Connect-PnPOnline $TenantUrl -Tenant $TenantName -ClientID $ClientID -CertificatePath $CertificatePath -CertificatePassword $SecureCertPassword # サイト一覧を取得(Communication, Team, Groupなどすべて) $sites = Get-PnPTenantSite # 結果格納用 $results = @() foreach ($site in $sites) { Write-Host "処理中: $($site.Url)" try { Connect-PnPOnline -Url $site.Url -Tenant $TenantName -ClientID $ClientID -CertificatePath $CertificatePath -CertificatePassword $SecureCertPassword $web = Get-PnPWeb -Includes RoleAssignments, RoleDefinitions foreach ($assignment in $web.RoleAssignments) { Get-PnPProperty -ClientObject $assignment -Property RoleDefinitionBindings, Member $roles = ($assignment.RoleDefinitionBindings | ForEach-Object { $_.Name }) -join ", " try { $GroupMembers = Get-PnPGroupMember -Identity $assignment.Member.LoginName foreach ($member in $GroupMembers) { $results += [PSCustomObject]@{ SiteUrl = $site.Url Principal = $member.Title LoginName = $member.LoginName Email = $member.Email Roles = $roles } } } catch { Write-Warning "グループメンバー取得失敗: $($site.Url) - $($assignment.Member.LoginName) - $_" # グループメンバーが取得できない場合は、グループ自体を結果に追加 $results += [PSCustomObject]@{ SiteUrl = $site.Url Principal = $assignment.Member.Title LoginName = $assignment.Member.LoginName Email = "" Roles = $roles } } } } catch { Write-Warning "失敗: $($site.Url) - $_" } } # 結果を表示 $results | Out-GridView -Title "全サイトのユーザー権限一覧" # CSVに出力 $results | Export-Csv -Path $OutputCsvPath -NoTypeInformation -Encoding utf8BOM Write-Host "CSVファイルに出力しました: $OutputCsvPath" -ForegroundColor Green Write-Host "処理が完了しました。" -ForegroundColor Green
💡 使用前の注意事項
セットアップスクリプトの編集箇所
SPO-Setup.ps1
の以下の部分を環境に合わせて変更してください:
# テナントの設定(環境に合わせて変更してください) $TenantName = "your-tenant.onmicrosoft.com" # ← 実際のテナント名 $TenantUrl = "https://your-tenant.sharepoint.com" # ← 実際のテナントURL # アプリケーションの設定 $ApplicationName = "sharepoint-client-ps" # ← 任意のアプリ名 $CertificatePassword = "YourSecurePassword123!" # ← 強固なパスワード
ファイル配置
以下のファイルを同じフォルダに配置してください:
SharePointOnline/ ├── SPO-Setup.ps1 # 初回セットアップ用 ├── SPO-PermissionAudit.ps1 # メイン実行用 ├── SharePointOnlineClientConfig.json # 設定ファイル(自動生成) ├── [アプリ名].pfx # 証明書(自動生成) ├── [アプリ名].cer # 証明書(自動生成) └── AllSitePermissions.csv # 出力結果(自動生成)
🚀 セットアップと実行手順
1. 初回セットアップ
環境準備とスクリプトのダウンロードが完了したら、セットアップを実行します:
# SharePointOnlineフォルダに移動 cd "C:\Scripts\SharePointOnline\" # 初回セットアップを実行 .\SPO-Setup.ps1
セットアップスクリプトが以下を自動実行:
- PnP.PowerShellモジュールのインストール
- Entra ID(Azure AD)アプリケーションの作成
- 証明書の生成とアプリケーションへの登録
- 設定ファイルの作成
2. 権限監査の実行
セットアップ完了後は、シンプルに実行できます:
# 権限監査実行 .\SPO-PermissionAudit.ps1
実行が完了すると:
- Out-GridViewで結果をプレビュー表示
- AllSitePermissions.csv
にフル結果を出力
📊 実行結果の活用方法
Excel での分析
CSVファイルをExcelで開いて:
- フィルター機能: 特定のサイトやユーザーの権限を絞り込み
- ピボットテーブル: ロール別の権限分布を分析
- 条件付き書式: 外部ユーザーや高権限ユーザーをハイライト
権限監査のポイント
- 外部ユーザーの確認: Email列で
#ext#
を含むアカウントをチェック - 高権限の監査: Roles列で「フル コントロール」を持つユーザーを確認
- 孤立したアクセス: 異動したユーザーの権限が残っていないかチェック
⚡ パフォーマンス最適化のポイント
このスクリプトでは、以下の最適化を実装しています:
1. 効率的な権限取得
# サイトごとに権限情報を取得 $web = Get-PnPWeb -Includes RoleAssignments, RoleDefinitions foreach ($assignment in $web.RoleAssignments) { Get-PnPProperty -ClientObject $assignment -Property RoleDefinitionBindings, Member $roles = ($assignment.RoleDefinitionBindings | ForEach-Object { $_.Name }) -join ", " }
2. エラーハンドリング
try { Connect-PnPOnline -Url $site.Url -Tenant $TenantName -ClientID $ClientID -CertificatePath $CertificatePath -CertificatePassword $SecureCertPassword $web = Get-PnPWeb -Includes RoleAssignments, RoleDefinitions # 権限処理... } catch { Write-Warning "失敗: $($site.Url) - $_" }
3. グループメンバー展開の適切な処理
try { $GroupMembers = Get-PnPGroupMember -Identity $assignment.Member.LoginName # メンバーごとに結果に追加 } catch { Write-Warning "グループメンバー取得失敗: $($site.Url) - $($assignment.Member.LoginName)" # グループ自体を結果に追加 $results += [PSCustomObject]@{ SiteUrl = $site.Url Principal = $assignment.Member.Title LoginName = $assignment.Member.LoginName Email = "" Roles = $roles } }
実行時間の目安
- 小規模環境(~50サイト): 5-15分
- 中規模環境(50-200サイト): 15-60分
- 大規模環境(200+サイト): 1時間以上
🔧 PnP.PowerShellのつまづきポイントと解決策
開発中に遭遇した主要な問題と解決方法をご紹介します。
0. 環境要件の課題
問題:
PnP.PowerShell モジュールがWindows PowerShell(5.1)で正常に動作しない PowerShell ISEでデバッグができない
解決策:
PowerShell 7.x + VS Code環境の構築:
# 1. PowerShell 7.xのバージョン確認 $PSVersionTable.PSVersion # Major: 7, Minor: 4 以上が必要 # 2. VS CodeでPowerShellターミナルを開く # Ctrl+Shift+P → "PowerShell: Show Integrated Console" # 3. VS CodeでのPowerShell設定確認 Get-Host # Name: Visual Studio Code Host が表示されればOK
重要なポイント:
- Windows PowerShell(青いアイコン)ではなく、PowerShell 7.x(黒いアイコン)を使用
- PowerShell ISEは使用不可のため、VS Code + PowerShell拡張で代替
- ターミナルの既定設定をPowerShell 7.xに変更推奨
1. モジュールインストールエラー
問題:
Install-Module : パッケージ 'PnP.PowerShell' が見つかりませんでした または Import-Module : 指定されたモジュール 'PnP.PowerShell' が読み込まれませんでした
解決策:
# PowerShell 7.xで実行(重要!) # 管理者権限でPowerShellを起動し、信頼できるリポジトリを設定 Set-PSRepository -Name PSGallery -InstallationPolicy Trusted Install-Module -Name PnP.PowerShell -Force -AllowClobber -Scope CurrentUser # インストール確認 Get-Module -ListAvailable -Name PnP.PowerShell
2. 証明書認証の設定
問題:
Connect-PnPOnline : AADSTS70002: Error validating credentials または Register-PnPEntraIDApp : 権限が不足しています
解決策: 証明書ベース認証の正しい設定手順:
# PowerShell 7.x + VS Codeで実行 # 2. Entra IDアプリの作成と証明書登録 $appInfo = Register-PnPEntraIDApp -ApplicationName "sharepoint-client-ps" -Tenant "your-tenant.onmicrosoft.com" -CertificatePassword $SecureCertPassword -Store CurrentUser
3. 権限取得エラー
問題:
Get-PnPRoleAssignment : アクセスが拒否されました または Get-PnPTenantSite : 権限が不足しています
解決策: Entra IDアプリケーションに最低限必要な権限を追加:
- Sites.Read.All: すべてのサイトコレクションの読み取り
- Group.Read.All: Entra IDグループ情報の読み取り
- User.Read.All: ユーザー情報の読み取り
4. 大量サイト処理時のタイムアウト
問題:
Connect-PnPOnline : リクエストがタイムアウトしました または 処理が途中で停止する
解決策: 接続リトライロジックの実装:
# PowerShell 7.x + VS Codeでの安定した処理 foreach ($site in $sites) { Write-Host "処理中: $($site.Url)" try { Connect-PnPOnline -Url $site.Url -Tenant $TenantName -ClientID $ClientID -CertificatePath $CertificatePath -CertificatePassword $SecureCertPassword $web = Get-PnPWeb -Includes RoleAssignments, RoleDefinitions # 権限処理を継続... } catch { Write-Warning "失敗: $($site.Url) - $_" # 次のサイトに進む continue } }
🔒 セキュリティ考慮事項
機密情報の保護
- 証明書ファイル: .pfxファイルは適切に保護
- 設定ファイル: 機密情報を含む設定ファイルのアクセス制御
- 実行ログ: 個人情報を含む可能性があるため適切に管理
📈 定期実行の設定
権限監査を定期的に実行する場合は、Windowsタスクスケジューラーを活用:
REM タスクスケジューラー用バッチファイル cd /d "C:\Scripts\SharePointOnline\" powershell.exe -ExecutionPolicy Bypass -File ".\SPO-PermissionAudit.ps1" pause
まとめ
SharePoint Onlineの権限管理は複雑になりがちですが、この自動化ツールにより:
- 効率化: 手動での確認作業を大幅短縮
- 可視化: 権限状況を一覧で把握可能
- 監査対応: コンプライアンス要件への対応を支援
PnP.PowerShellは強力なツールですが、認証周りで躓きやすいポイントがあります。今回紹介した解決策を参考に、ぜひ権限監査の自動化にチャレンジしてみてください。
セキュリティとガバナンスの向上に、このツールが役立てば幸いです。
参考情報: - PnP PowerShell 公式ドキュメント - Microsoft 365 コンプライアンス センター
注意: 本ツールは動作確認済みですが、しっかりと内容をご確認の上ご利用ください。