
GrafanaのTeamとOrganizationでテナント分離がどこまでできるか検証してみた
こんにちは、ゲームソリューション部のsoraです。
今回は、GrafanaのTeamとOrganizationでテナント分離がどこまでできるかを、実際に画面で確認してみたことについて書いていきます。
複数のチームやプロジェクトで1つのGrafanaを共有する場合、「チームAのダッシュボードやログはチームAの人にしか見せたくない」という要件が出てきます。
Grafana Enterprise / Grafana Cloudにはそのための機能がありますが、OSS版でどこまでできるのかを把握しておきたかったので、触ってみて確認していきます。
Grafanaの区切りとは
Grafanaには「見えるものを分ける」ための区切りとして、Organization・Team・フォルダの3種類があります。
それぞれの関係は以下のとおりです。

ユーザーはインスタンスに1つだけ存在し、Organizationごとに「所属しているか」と「そのOrganizationでのロール」を持ちます。
TeamとフォルダはOrganizationの中に閉じるので、別のOrganizationからは見えません。
ロールは以下の4つで、OSS版ではこれ以外のロールを作ることはできません。
| ロール | 単位 | できること |
|---|---|---|
| Grafana Server Admin | インスタンス | Organizationの作成、全ユーザーの管理、サーバー設定の閲覧 |
| Admin | Organization | そのOrganization内のすべて。フォルダ権限で制限をかけられない |
| Editor | Organization | ダッシュボードの作成と編集、ExploreとDrilldownの利用 |
| Viewer | Organization | ダッシュボードの閲覧のみ。ExploreとDrilldownはメニューに出ない |
ちなみに、固定ロールの付け外しやカスタムロールの作成といったRBACの機能はGrafana Enterprise / Grafana Cloud限定です。
検証構成
Grafana本体は、以下の記事でECS Fargateに構築した構成をそのまま使います。

Grafanaのバージョンは13.2.1で、データソースとしてCloudWatch・X-Ray・AMPを登録済みです。
今回は権限の設定を手で変えて画面の変化を見たいので、Terraformは使わずにGrafanaの画面から設定しています。
検証1で使う登場人物は以下のとおりです。
| Team | フォルダ | ダッシュボード | ユーザー |
|---|---|---|---|
| team-a | team-a | team-a-dashboard | usera |
| team-b | team-b | team-b-dashboard | userb |
| (なし) | common | common-dashboard | (なし。全員に見せるフォルダ) |
検証1: フォルダ権限 + Team
Teamとフォルダの作成
Administration → Users and access → Teams → New teamからteam-aとteam-bを作成します。

「Auto-create a team folder」にチェックを入れると、Teamと同じ名前のフォルダが所有者付きで作られます。
なお、このチームフォルダ機能はpublic previewで、feature toggleのteamFoldersとfoldersAppPlatformAPIが必要です。
また、フォルダの所有者はTeamとフォルダの紐付けを示すだけで、フォルダ権限は変わらないため、後述の権限設定は別途必要です。

同じ要領でユーザーとダッシュボードも作成し、adminで見ると以下のようになります。

フォルダ権限の設定
team-aフォルダのManage permissionsを開くと、初期状態では以下のようになっています。

Admin行は鍵アイコンで固定されていて削除できません。
Organization Adminの権限は上書きできず、Organization内のすべてのリソースにアクセスできることが以下ドキュメントに記載があります。
EditorとViewerの行は「そのロールを持つOrganization内の全員」に対する権限で、フォルダ作成時にデフォルトで付いてきます。
これを残したままだと、Viewerロールを持つ全ユーザーがこのフォルダを見られる状態です。
そこで、EditorとViewerの行とUserのadminの行をゴミ箱アイコンで削除し、Add a permissionからTeamのteam-aにViewを追加します。

残る権限は「Admin行(固定)+ team-aのView」だけになります。
team-bフォルダも同じように設定し、commonフォルダはデフォルトのまま残しました。
なお、フォルダに入れていないダッシュボードはフォルダ権限の対象外なので、分離したいダッシュボードは必ずフォルダに入れる必要があります。
ユーザーごとにログインして確認
adminからログアウトし、userbでログインしてみます。

team-bとcommonだけが表示され、team-aフォルダは一覧に出てきません。
team-a-dashboardのURLを直接開いてみると、403で拒否されました。

userbはViewerロールなので、サイドメニューにExploreとDrilldownも出ていません。

ExploreとDrilldownはどちらもdatasources:explore権限で動いていて、デフォルトではEditor以上にしか付いていないためです。
Teamのメンバーであるかどうかは関係ありません。
useraでログインすると、こちらはteam-a側だけが見えています。

ダッシュボードの分離という意味では、フォルダ権限とTeamで問題なくできています。
ExploreとDrilldownはTeamで分けられない
ではuseraをEditorに上げてみます。
Administration → Users and access → Users → usera → Organizations → Change roleでEditorにします。

再度useraでログインすると、ExploreとDrilldownがメニューに出てきました。

Exploreを開いてX-Rayのデータソースを選択してみると、サンプルアプリのトレースが表示されました。

Drilldown → Metricsを開いてみると、AMPに入っている全ECSタスクのメトリクスが並んでいます。

useraはteam-aのメンバーですが、Teamやフォルダ権限とは関係なく、Organizationに登録されているデータソースのデータはすべて見えています。
デフォルトではOrganization内の任意のユーザーがすべてのデータソースにクエリでき、Viewerであってもダッシュボードに存在するクエリだけでなくあらゆるクエリを発行できることが、以下ドキュメントに記載があります。 ユーザーやTeamごとにデータソースへのクエリを制限する「Data source permissions」はGrafana Enterprise / Grafana Cloud限定の機能です。
Viewerでもデータは取れる
ここまでで「Editorだと全部見える」ことはわかりました。
では全員をViewerにしてExploreとDrilldownを消してしまえば分離できるのか、を確認してみます。
Viewerのuserbでログインしたセッションでは、画面上はExploreもDrilldownも出ておらず、ダッシュボードもteam-bのものしか見えていません。
この状態で、Grafanaのクエリ用APIをBasic認証で直接叩いてみます。
まず、ログインしているユーザーなら誰でも読める/api/frontend/settingsからデータソースの一覧を取得します。
curl -s -u userb:<password> https://<GrafanaのURL>/api/frontend/settings \
| python3 -c 'import sys,json; ds=json.load(sys.stdin)["datasources"]; [print(v.get("uid","-"), v.get("type","-"), k) for k,v in ds.items()]'
実行結果は以下のとおりです。
efxi4eq3640zkd grafana-amazonprometheus-datasource amp
cfxi7l37mybcwe grafana-postgresql-datasource aurora
afxi2ruaut43ka cloudwatch cloudwatch
bfxi2wkgnarcwe grafana-x-ray-datasource grafana-x-ray-datasource
Viewerでも、Organizationに登録されている4つのデータソースがすべて見えています。
続けて、AMPのデータソースに対してPromQLを投げてみます。
curl -s -u userb:<password> -H 'Content-Type: application/json' \
-X POST https://<GrafanaのURL>/api/ds/query \
-d '{"from":"now-1h","to":"now","queries":[{"refId":"A","datasource":{"uid":"efxi4eq3640zkd"},"expr":"ecs_task_cpu_reserved_None","instant":true,"intervalMs":60000,"maxDataPoints":100}]}'
status 200で、全ECSタスクの値が返ってきました。
status: 200
aws_ecs_service_name=grafana-single-backend ecs_task_cpu_reserved_None -> 512
aws_ecs_service_name=grafana-single-frontend ecs_task_cpu_reserved_None -> 512
CloudWatchのデータソースでも同じことを試したところ、ECSのCPUUtilizationが直近1時間分返ってきました。
つまりViewerロールで隠れているのはメニューだけで、データソースにクエリする権限そのものは残っています。
「見えない」と「取れない」は別物で、OSS版においてTeamやユーザーの権限を設定しても、データ取得を制限できないことがわかりました。
Organization Adminのフォルダ権限は変更できない
最後に、userbのOrganizationロールをAdminに上げてみると、team-aフォルダも見えるようになりました。
フォルダ権限の画面でAdmin行が鍵アイコンで固定されていて削除も変更もできなかったとおり、Organization Adminに対してはフォルダ権限で制限をかけられません。
Teamで区切る運用では、テナント側のユーザーはEditorが上限です。
ダッシュボードやフォルダの作成はEditorでもできるので、Adminが必要になるのはユーザー管理やデータソースの追加をさせたいときだけです。
検証2: Organization分離
検証1の結果を受けて、次はOrganizationで分けてみます。
Organizationはデータソースごと分かれるので、ExploreやDrilldownから他のOrganizationのデータに到達できないことを確認していきます。
Organizationの作成
Organizationの作成はGrafana Server Adminにしかできません。
Server Adminはユーザー詳細の「Permissions → Grafana Admin」で切り替えるインスタンス単位のフラグで、Organizationsに表示されるOrganizationロールとは別物です。

Server Adminにすると、サイドメニューのAdministration → GeneralにStats and license / Settings / Organizationsが増えます。

Administration → General → Organizations → New orgでOrgAを作成します。

このOrganizations画面はインスタンス全体の一覧なので、どのOrganizationにいても同じものが表示されます。
Organizationは階層ではなく並列で、どこから作っても結果は同じです。
OrgAを作成すると、左上にOrganizationの切り替えが出るようになります。

Organizationを切り替えてみる
OrgAに切り替えると、ダッシュボードもデータソースも何もない状態です。

Drilldown → Metricsを開いても、Prometheusデータソースが未設定と言われます。

Main Org.で登録したCloudWatch・X-Ray・AMPのデータソースは、Main Org.の中にしか存在しません。
「Grafana本体がAWSに繋がっている」のではなく「Main Org.のデータソースがAWSに繋がっている」という関係です。
ダッシュボード・データソース・アノテーション・フォルダ・Team・アラートがOrganizationごとに分離されることは、以下ドキュメントに記載があります。
OrgAのユーザーでログインして確認
OrgAにのみ所属するusera2をEditorで作成し、ログインしてみます。
ユーザーはUsers → New userで作成すると「今いるOrganization」にViewerで追加されるので、OrgAに切り替えた状態で作成し、あとからロールをEditorに変更しました。

Exploreのデータソース選択肢は組み込みの「-- Grafana --」と「-- Mixed --」だけで、CloudWatchもAMPも出てきません。
Editorなので検証1と同じくExploreもDrilldownも使える状態ですが、叩く先のデータソースがOrganizationに存在しないため、何も見えません。

1つのOrganizationにしか所属していないため、Organizationの切り替えも表示されていません。
Organization分離の代償
Organizationで分けると綺麗に分離できる一方で、以下の代償があります。
- 運用者が全テナントを見たい場合、全Organizationに所属してOrganizationを切り替えながら見ることになる
- 1つのダッシュボードにテナントAとBを並べることはできない
- データソース、ダッシュボード、アラートルール、通知先、サービスアカウントをOrganizationごとに作る必要がある
- 共通ダッシュボードを直したらOrganizationの数だけ反映する
- ユーザーごとにOrganizationへの所属とロールを設定する
- OIDC連携なら
org_mappingでグループからOrganizationとロールを決められる
- OIDC連携なら
Organizationはインフラではなく設定の仕切りなので、Grafanaのタスク・設定DB・通信経路は1つのままです。
複製の手間はTerraformで吸収できるので、実際に効いてくる代償は「横断で見られない」ことになります。
補足: Organizationで分けてもデータソース側は別途分ける必要がある
Organization分離はデータソースの窓口をOrganizationごとに分けているだけです。
OrgAでデータソースを作れるユーザー(Organization Admin)がいれば、Grafanaのタスクロールの権限が届く範囲はすべて見えてしまいます。
今回の環境では、GrafanaのタスクロールがCloudWatchとAMPの読み取り権限をそのまま持っていたため、OrgAでCloudWatchデータソースを「AWS SDK Default」で作ればMain Org.と同じものが見えます。
これを防ぐには、テナント側のユーザーにOrganization Adminを渡さずデータソースは運用側が作ることと、Grafanaのタスクロールにはsts:AssumeRoleだけを持たせてデータソース設定の「Assume Role ARN」でテナントごとのロールを指定することを、セットで守る必要があります。
テナントごとにAWSアカウントが分かれている環境なら、Organization = アカウントの対応にしてクロスアカウントでAssumeRoleするのが素直です。
同一アカウントで完全に分けたい場合は、保存先をLoki / Tempo / AMPに寄せてテナントIDで分ける構成になりますが、こちらは機会があれば別で試してみようと思います。
補足: Grafana Enterprise / Grafana Cloudだとどうなるか
今回の検証で見つかった穴は、Grafana Enterprise / Grafana Cloudの機能で塞げるようです。
実際に触れる環境がないため、公式ドキュメントの記載をベースに記載します。
Data source permissionsは、データソースごとに「クエリできるユーザー・Team」を絞れる機能です。
ドキュメントには、デフォルトではOrganization内の任意のユーザーがデータソースにクエリできること、権限はusers / service accounts / teams / rolesに対して付与できることが記載されています。
Available in Grafana Enterprise and Grafana Cloud.
By default, data sources in an organization can be queried by any user in that organization.
RBACは、固定ロールの付け外しやカスタムロールの作成ができる機能です。
これを使うと「Viewerだが Exploreは使える」「Editorだが Exploreは使えない」といったロールが作れます。
Available in Grafana Enterprise and Grafana Cloud.
Team Syncは、認証プロバイダー側のグループとGrafanaのTeamを同期する機能です。
Team sync lets you set up synchronization between your auth providers teams and teams in Grafana.
Data source permissionsを使えば、1つのOrganizationの中でデータソースをTeamごとに分けつつ、運用者は横断ダッシュボードを持てます。
Organization分離の代償である「横断で見られない」を解消できるのがEnterpriseの価値です。
テナント分離の要件がある場合は、Organization分離で足りるのか、横断ダッシュボードが必要でEnterpriseになるのかを最初に確認しておく必要があります。
最後に
今回は、GrafanaのTeamとOrganizationでテナント分離がどこまでできるかを、フォルダ権限 + TeamとOrganization分離の2つの方式で実際に画面を見ながら確認してみました。
この記事がどなたかの参考になれば幸いです。









