Power BIでの行レベルセキュリティを考える

Power BI 勉強会 @ 東京 #18で話をさせていただきました。
以下、本記事に関する発表スライドです。
https://www.slideshare.net/secret/bSN3YOYsSndVcU

# 本記事の目的
組織で業務システムのデータベースで管理しているデータの可視化をする場合、権限管理について考える必要がある。

通常は業務システムのアプリケーション側で行レベルのセキュリティを担保している場合が多いと思うが、同データベース上のデータをPower BIで可視化してレポートを公開する場合に、どのように同じレベルの権限制御を実現できるか考えた。（もっと良い方法があれば教えてください。）

前提とするシナリオは以下の通り。

- 業務で利用するDBには複数プロジェクトのデータが横断して格納されている
- 社員は自身の所属するプロジェクトのデータのみを閲覧することができる
- Power BIレポートの閲覧者は一般ユーザ（全社員）を想定する
- Power BIレポートの作成者も一般ユーザ（全社員）を想定する
- 権限の認証のためのActive Directoryを導入済

※ 「一般ユーザ」は、IT部門など一部の特権ユーザに限らない全社員という意味

結論を先に書くと、エンタープライズの業務データでは行レベルセキュリティの要件が出てくる可能性が高く、これを（運用面も考慮して）実現するためには、Direct Query（SSO）でのPower BI利用が有効になりそう、ということだ。


# 実現したいこと
業務システムで利用しているデータベースには、業務データが入っている。社内では複数のプロジェクトが並行して行われており、データベースには全プロジェクトの業務データが入っている。一方、ユーザは自身のアサインされている一部のプロジェクトのデータに対してのみ、アクセスが可能。

業務システムはログインユーザに対して、権限テーブルと業務データを組み合わせて適切なデータを表示してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/3734c8ca-1889-67fd-b1be-39e4cd8f1bd0.png)

今回考えるのは、これがPower BIレポートの閲覧に代わった場合、どうなるかだ。
先ほどの図でアプリが担ってくれていた行レベルのアクセス権限制御を、何かで肩代わりしなければならない。
やりたいことは先ほどと同じ、「各ユーザに対して、本人が参照権限を持つデータだけを見せたい」だ。
Power BIのレポート環境で同じことを実現するためには、何が良いのだろうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/581d1225-e960-53f2-3c40-1c9aedd4f255.png)


ひとつの方法としては、以下のようにプロジェクト毎に別のワークスペースを用意するというものがある。
こうすれば、プロジェクトの情報は対応するworkspace内に閉じているので安全に運用できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/6be6659f-5323-d564-313d-8a2f03d30c1a.png)


一応要件は実現できそうではあるが、以下のような懸念があり、あまり良い実現案とは言い難い。

- プロジェクトの数だけワークスペースとレポートを準備する必要があり、管理が煩雑になる
- 複数プロジェクトの兼務者がプロジェクトを横断してデータを見ることができない

これらの懸念を踏まえると、やはり1つのレポートに対して、レポート閲覧者によって見えるデータが異なる状態を実現したい。言い換えると「1つのテーブルに対して本人の権限にあった行だけにアクセスができる」、すなわち行レベルのセキュリティを実現したい。

# 行レベルセキュリティの実現候補
Power BIではデータソースに対する接続方式（Connection Type）は3種類ある。

1. インポート
2. ライブ接続
3. Direct Query

それぞれの接続方式の違いについては、以下の図が分かりやすい。
重要なポイントは、「どこにデータを持つか」「どこでモデル設計をするか」といったところ。
>![Power-BI-Connection-Types-Diagram-768x432.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/6f41e2b5-dd7e-85c1-61a0-f21a4365e03c.jpeg)
> Power BI Connection Types
> https://www.teamscs.com/2016/08/power-bi-connection-types/

それぞれの接続方式において、どのように行レベルセキュリティが実現できるかを考えていく。

## 1. インポート
インポートでは、データはPower BI Serviceのデータセット上（意識しないが裏側はAnalysis Services）で持つ。
Power BI Desktop側でロールとルールを定義しておくことにより、ここで行レベルのセキュリティが実現できる。
Azure ADで認証されたユーザ名（USERPRINCIPALNAME()）と権限テーブルを使うことによって、業務データをアクセスユーザに応じて動的にフィルタできる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/dd1cb1d5-53a1-f085-9619-0a072566938a.png)

> Power BI での行レベルのセキュリティ (RLS)
> https://docs.microsoft.com/ja-jp/power-bi/admin/service-admin-rls

## 2. ライブ接続
ライブ接続は、データ部分がAnalysis ServicesとしてPower BI Serviceの外部に出た形になる。
Importの場合とほぼ同じイメージで行レベルセキュリティを実現できる。
この場合、行レベルセキュリティはAnalysis Services側で行うが、同時にデータやモデルの設計もAnalysis Services側で実施することになる。Power BI Desktop側ではデータやモデルの設計ができなくなる点には注意が必要。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/bee2095f-cd27-d0e4-2874-666bd7a05e29.png)

ライブ接続を選択した場合、Power BI Desktop側では「レポート」タブしか表示されない。Tabular Modeの場合にはメジャーの作成に限り可能だが、それ以外はAnalysis Services側で用意されたデータやモデルを使って、見せ方を作りこむだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/2592ca68-3752-555c-be6b-e0fdf22c80a7.png)


## 3. Direct Query
Direct Queryの場合はデータは元々のデータベース側で持つ。
データソースであるSQL Serverなどでセキュリティロールを設定しておくと、Power BI経由で毎回データソースにクエリが送信される。
Azure Active DirectoryでSingle Sign On(SSO)したユーザーの資格情報に基づいてデータにセキュリティ規則が適用できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/a3ed10e9-fac5-d448-3fbd-8248c13bfced.png)

ただしDirect Queryによる接続は何のデータソースに対してもSSOできるわけではなく、Oracleにはまだ対応していない模様。
現時点では、以下のようなデータソースに対してSSOが可能である。

- Azure SQL Database
- Azure SQL Data Warehouse
- SQL Server

> Power BI データ ソース
> https://docs.microsoft.com/ja-jp/power-bi/connect-data/power-bi-data-sources
 
> Azure SQL Database と DirectQuery
> https://docs.microsoft.com/ja-jp/power-bi/connect-data/service-azure-sql-database-with-direct-connect

Direct Queryを選択した場合、Power BI Desktop側では「データ」タブは表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596092/39c855eb-f2e3-86d0-1df1-22588b1857ef.png)


# その他の観点
3つの接続方式のどれを採用するかを考えるときには、以下の観点も重要である。

### 観点1. パフォーマンスと負荷
インポートやライブ接続の場合、データはAnalysis Servicesに格納されているため、Power BIのDAXをそのまま使ってデータの問合せが可能である。一方Direct Queryの場合、毎回DAXをSQLに変換してデータソースに問い合わせる必要がある。そのため負荷が高くなりパフォーマンスが低下する。したがってパフォーマンスの観点ではインポートやライブ接続が有効。（同じ理由で一部のDAX関数はDirect Queryでは利用不可）

### 観点2. レポート作成者の権限
今回はレポートの閲覧者に焦点を当てたが、レポート作成者として誰を想定するかも重要である。レポート作成者の場合、（Power BI Serviceを通じてではなく）Power BI Desktopを通じて、直接データベースに接続するためである。IT部門のユーザなど（プロジェクト横断したアクセスが許される）特権ユーザだけがレポートを作成する場合は良いが、そうでないならば元のデータベースに対して事前にアクセス権限を設定しておく必要がある。この場合にはDirect Queryが有効。

### 観点3. データに期待する鮮度
インポートやライブ接続の場合、データソースからAnalysis Servicesへは定期的にデータ連携が行われており、ユーザがレポートにアクセスされたときにはAnalysis Servicesのデータを表示する。データソースからAnalysis Servicesへのデータ更新は柔軟に設定が可能ではあるが、リアルタイムではない。一方、Direct Queryはユーザがレポートにアクセスする度に、元のデータソースに対して問合せを行い最新の値を取得する。リアルタイムに準じたデータ鮮度を期待する場合はDirect Queryが有効。

# まとめ
Power BIの3つの接続方式のいずれを採用しても、行レベルセキュリティは実現できる。
ただし実現の方法には違いがあり、それぞれ長短があるため、要件に照らして採用を決定する必要がある。

社内のデータ活用を推進しようという動きが高まっている中で、一般的に広く社内の全ユーザがレポートの作成者になりうることを前提にする組織が多いように思う。

これを考慮すると、上記の観点2で述べたように、元のデータベースへの行レベルセキュリティを担保しながら同じセキュリティレベルをレポートの閲覧者にも適用できるDirect Query（SSO）は有効な手段に思える。