Grafana IAMの深淵:マルチテナント環境における「究極のアクセス制御」とデータ分離の技術
オブザーバビリティの世界において、Grafanaはもはや単なる可視化ツールではない。それは組織の「信頼のハブ」だ。しかし、多くのエンジニアが陥る罠がある。それは「とりあえず全員に閲覧権限を与える」という怠惰な設計だ。
マルチテナント環境において、誤った権限設定は単なるセキュリティリスクではない。それは、あるチームの障害が他チームのダッシュボードを汚染し、不要なクエリでデータソースを圧迫する「オブザーバビリティの崩壊」を招く。
本稿では、GrafanaのGUIを飛び越え、API駆動で構築する「境界が明確で、かつセキュアな」マルチテナント・アーキテクチャの極意を解説する。
—
1. 組織設計の再定義:Orgs vs Folders vs Teams
Grafanaの「Organizations」機能は、論理的な分離の最終手段だ。だが、運用コストは最大になる。私は、「同一Org内でのフォルダベース制御」を基本とし、コンプライアンス要件が極めて高い場合のみ「Org分離」を行う設計を推奨する。
なぜか?
Orgを跨ぐデータソースの共有は複雑であり、認証基盤(LDAP/OIDC)との同期が地獄と化すからだ。
- フォルダ階層: チームごとにトップレベルフォルダを割り当て、`Viewers`と`Editors`を同期させる。
- RBACの自動化: チームの入退社とGrafanaの権限を完全にデカップリングするため、Terraformでの構成管理が必須である。
—
2. API駆動による「権限の完全自動プロビジョニング」
GUIでポチポチと設定しているようでは、プロとは呼べない。Grafanaの管理はすべてコード化(IaC)すべきだ。以下は、チーム単位でフォルダ権限を自動適用するGo言語によるプロトタイプ・アプローチだ。
// チームIDとフォルダIDを紐付け、アクセス権を強制適用するスニペット
func syncFolderPermission(client grafana.Client, folderID int64, teamID int64, role string) error {
// 既存権限を上書きし、不要なアクセスを剥奪する(最小権限の原則)
permission := grafana.Permission{
TeamId: teamID,
Role: role, // “Viewer” or “Editor”
}
// API経由で権限を更新。ここで失敗することは許されない
_, err := client.UpdateFolderPermissions(folderID, []grafana.Permission{permission})
return err
}
極意: APIを叩く際は、必ず`admin`ロールを持つService Accountを使用すること。また、APIレートリミットを回避するため、キャッシュを挟んだ差分同期パイプラインを構築せよ。
—
3. 行レベルセキュリティ(Row-level Security)の裏技
マルチテナント環境で最も頭を悩ませるのが、「AチームにはAチームのデータだけを見せたい」という要件だ。データソース側でクエリを制限するのは非効率すぎる。
ここで使うのが、「ダッシュボード変数とデータソースのクエリ置換」による擬似的なRow-levelセキュリティだ。
実装ステップ:
1. グローバル変数 `__user.login` の活用: ダッシュボードのクエリに`${__user.login}`を埋め込む。
2. データソース側のフィルタリング:
- 例えばPrometheusであれば、`up{team=~”$team_label”}` のように変数を渡す。
- Grafanaの「Data Source Permissions」と組み合わせ、特定のユーザー以外には特定のクエリを発行させないようプロキシ側で制御する。
高度なハック: Grafanaの「Dashboard Templating」の`Custom`フィールドに、ユーザーの属性情報をOIDCから注入し、それに基づいてクエリのWHERE句を動的に生成する構成が最も堅牢だ。
—
4. アーキテクチャ最適化:メモリとクエリ負荷の管理
マルチテナント環境で「あるユーザーの重いクエリ」が全体のダッシュボードを凍結させる事態を防ぐ必要がある。
- Query Caching: Redisをサイドカーとして配置し、頻繁にアクセスされるダッシュボードの計算済み結果をキャッシュせよ。
- Quota Management: Grafanaの`[quota]`設定を徹底する。
- `org_user_limit`: 組織ごとのユーザー数上限。
- `global.max_concurrent_queries`: これを厳格に設定し、単一ユーザーがデータソースをDOS攻撃状態にするのを防ぐ。
- メモリ監視: Grafanaプロセスのメモリ消費は、Dashboardのレンダリング回数に比例する。`pprof`を用いて、特定のダッシュボードがヒープをどれだけ占有しているかを定期的にプロファイリングせよ。
—
5. 伝説的アーキテクトからの助言
最後に、技術以上に大切なことを伝える。
「権限設定は、人間が手を出せない場所に置け」。
TerraformやPulumiで構成を管理し、CI/CDパイプラインを通さない変更は即座にCIによってリセットされる環境を構築すること。「設定変更の痕跡」がGitに残らない環境は、やがて腐敗する。
君たちが構築するのは、単なるグラフの箱ではない。組織の意思決定を支える「信頼のインフラ」だ。細部に宿る神を信じ、設定の隅々までコードで支配せよ。
次回の講義では、Grafana Lokiを用いた「マルチテナント・ログ隔離の物理的アプローチ」について触れることにする。準備をしておくように。