Power BI から Azure Functions に Azure AD 認証経由で接続する

この記事では、Power BI のデータソースとして Azure Functions を使う方法を紹介します。またセキュリティには、Azure AD を使った OAuth 2.0 認証を利用します。
※それぞれのテクノロジーについての詳細はこの記事では説明しません。

# Azure Functions の作成
1\. [Azure Portal](https://portal.azure.com) より Function App を検索して選択。
<img width="556" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/1c23b7e9-7d5d-119b-b655-3ed6c0b4fddf.png">

2\. 必要項目を設定して作成。ここでは名前を datasourcefunction としました。
<img width="603" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/a640e317-260f-3fce-0f33-8ee7dee430b3.png">

3\. HTTP トリガーで実行される C# を選択。
<img width="634" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/44e22bea-67e8-ebcc-f559-7caba7d99330.png">

4\. 検証のため、ここでは単純な　JSON 配列を返すコードを利用。中身を以下コードに差し替え。

```csharp
using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    List<User> users = new List<User>();
    users.Add(new User(){ UserId = 1, Name = "User 1"});
    users.Add(new User(){ UserId = 2, Name = "User 2"});
    users.Add(new User(){ UserId = 3, Name = "User 3"});
    return req.CreateResponse(HttpStatusCode.OK, users);
}

public class User
{
    public int UserId {get; set;}
    public string Name {get; set;}
}
```

5\. 実行して結果を確認。期待した JSON が返ってくれば完了。

6\. 次に認可レベルを設定。「統合」メニューより、「Authorization level」を「Anonymous」に設定して保存。
<img width="483" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/07826291-1429-f0ac-c8f3-d8a8ec09e768.png">

7\. 「関数の URL の取得」をクリックして、アドレスを確認。後で利用するので保存しておく。
<img width="429" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/ea9ad826-79b5-1dca-b804-0b0705fc60c3.png">

### Azure AD 認証の設定
1\. 作成した Azure Functions を選択し、「プラットフォーム機能」をクリック。
<img width="658" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/c170a219-848f-b998-2618-fc17da6c6260.png">

2\. 「認証/承認」をクリック。
<img width="605" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/84d30455-b71e-eb3d-705f-40ea838531af.png">

3\. 「App Service 認証」を「オン」、「要求が承認されない場合に…」を「Azure Active Directory でのログイン」にして、Azure Active Directory の項目をクリック。右側のブレードより「管理モード」で「簡易」を選択。最後に 「OK」をクリック。
<img width="643" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/f01f9cd5-3751-c5b9-9301-125d964950e2.png">

4\. 一旦保存した後、再度「Azure Active Directory」をクリックし、「管理モード」で「詳細」を選択。「許可されるトークン対象ユーザー」にホスト名までのアドレスを追加。最後のスラッシュを付けないように気を付ける。
※　Web ブラウザなどで使う場合は既定のものだけで OK ですが、Power BI で使う場合はホスト名を追加する必要があります。
<img width="552" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/946a8f9d-df9a-a6bb-bdbc-ad224f83a71e.png">

5\. 再度「保存」をクリックして設定は完了。

### テスト
1\. ブラウザで関数の URL にアクセス。認証にリダイレクトされることを確認。
<img width="510" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/4b2a0249-f29c-8ebd-b81b-4758c6727a96.png">

2\. コンセント画面で「OK」をクリックし、結果が出ることを確認。
<img width="376" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/66bf6dd0-5ff2-b25f-d605-4bb1227db8a6.png">

# Power BI から接続
Azure Functions の準備ができたので、Power BI から読み込んでみます。

1\. Power BI Desktop を起動し、「データを取得」をクリック。
<img width="825" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/f4d63ab5-619c-812f-c861-414dd48941d0.png">

2\. 「Web」を検索して「接続」をクリック。Azure Functions のアドレスを入力して「OK」をクリック。
<img width="526" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/b55d46b3-e923-64cd-6e8a-1596079649fa.png">

3\. 「組織アカウント」を選択して「サインイン」をクリック。組織ユーザーでサインイン。サインインが完了したら「接続」をクリック。

4\. JSON 配列が結果として返るため、複数の Record が結果として表示される。ここで「テーブルへの変換」をクリック。ダイアログが出るので、オプションは既定のまま「OK」をクリック。
<img width="521" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/a64ba17f-7119-9541-f560-0a111cc0c328.png">

5\. テーブルに変換後、列名の横に出るアイコンをクリックしてレコードを展開。
<img width="335" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/b773f082-8783-0b92-46c6-5a5212860fc7.png">

6\. 必要な列を選択して、「OK」をクリック。ここでは「元の列名を…」のチェックを外して列名のみを採用。
<img width="446" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/57097a23-a615-5866-d833-f9860cee29da.png">

7\. 最後に「閉じて適用」をクリック。
<img width="346" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/4d2eaf15-1a3d-8a2d-dd94-643e0ba6750e.png">

8\. 必要に応じてレポートを作成。

# ログインユーザーの情報を Azure Functions で取得
Azure AD と連携しているので、ログイン情報を Azure Functions で取得できます。その情報で例えばデータをフィルターすることも出来ますし、他の用途にも使えます。ユーザーの情報は ClaimsPrincipal クラスから取得可能です。

1\. 関数のコード上部に、using ステートメントを追加

```csharp
using System.Security.Claims;
```

2\. Run メソッド内で UPN を取得するコードを追加。ここではログに結果を表示。

```csharp
 log.Info(ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value);
```

3\. Power BI Desktop より「最新の状態に更新」をクリック。
<img width="399" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/a3df8deb-a4ec-f903-ff85-79fd3c8d75ad.png">

4\. Azure Functions のログを確認。
<img width="563" alt="Capture.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/214116/8ed47ee0-f6e0-45d3-9797-e0c017d4e4b1.png">

# まとめ
Power BI では実に様々なデータソースを利用できますが、データソースによってできることに制限がある場合もあります。そのような場合に、Azure Function をプロキシのように利用することでより柔軟な接続が実現できそうです。是非試してみてください。

### 参考
[Power BI Desktop ダウンロード](https://www.microsoft.com/ja-jp/download/details.aspx?id=45331)
[ClaimsPrincipal クラス](https://msdn.microsoft.com/ja-jp/library/system.security.claims.claimsprincipal(v=vs.110).aspx)