Media Services の認証方式の変更について

以前に記事だけ取り上げましたけど勘違いしていたので改めて。

基本的には上記Blogに書かれているとおりですが、ACS(Access Control Services)ベースを使った認証方式が2018年6月22日で廃止されるのでAzure ADを使った認証方式に変えましょう、というのが主旨になります。
※で、ACS使ってないやーとか思ってたのですけどこれまでのMedia Servicesアカウントとアカウントキーの組み合わせでアクセスするのもACS使ってるのでアウト=基本的に既存コードなどは対応しないといけない、ということでした。

さて猶予期間は1年弱ありますが、中身を理解してさっさと対応してしまいましょう。新しい方式はAzure ADを使うというのと、エンドポイントを柔軟に設定できるので将来的にAzure StackにMedia Servicesがきても対応することができます。

なお字幕生成などが行えるMedia Analyticsも同じだと思うので同じように対応しましょう。

Overview

しないといけない点は一言でいえばMedia ServicesのAPIを呼び出す際にAuthorizationヘッダーにBearerトークンを渡すようにする、だけです。Bearerトークンは他のAPIなどと同じようにAzure ADとやりとりして取得します。Media Services用の.NET SDKの場合はNuGetパッケージ (windowsazure.mediaservices 4.0.0.4以降)を更新して CloudMediaContext の生成方法を少しかえるだけとなります。設定項目は多いですが理屈がわかればそれほどでもないので大丈夫です。※他の言語用も概ね同じでしょう。

さてAzure ADを使用してトークンを取得する場合、いくつか方法があります。1つはユーザーと対話的にログイン処理を行う方式、もう1つはサービスプリンシパル(Service Principal)を使う方式です。

ユーザーの対話ログインの場合はActive Directory Authentication Library(ADAL)を使うと、いうほど苦労せずに実装できます。(Azure PowerShellなどでも使われているログイン画面がポップアップで表示されるやつですね)
サービスプリンシパルを使う場合はいくつか事前準備が必要になりますが、対話が不要なのでサービスアプリケーションやバッチ処理など裏側で処理させる場合やWebアプリケーションの裏側で使う場合はこちらが必須になるかと思います。

How to

1. 対話式ログオンの場合

では順番に見ていきましょう。ここでは.NET Frameworkの場合を挙げておきます。まず最初に対話ログインの方法。NuGetパッケージは忘れず追加しておきましょう。

namespace mediaservicesample
{
    using System;
    using System.Linq;
    using Microsoft.WindowsAzure.MediaServices.Client;

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.Write("input your AzureAD tenant name: ");
                var tenantName = Console.ReadLine();
                Console.Write("input your media services endpoint: ");
                var endpoint = Console.ReadLine();

                var tokenCredentials = new AzureAdTokenCredentials(
                                        tenant: tenantName, // Azure ADテナント名
                                        azureEnvironment: AzureEnvironments.AzureCloudEnvironment
                                        );
                var tokenProvider = new AzureAdTokenProvider(tokenCredentials);
                var mediaContext = new CloudMediaContext(apiServer: new Uri(endpoint), // Media Services REST API エンドポイント
                                                        tokenProvider: tokenProvider
                                                        );

                var asset = mediaContext.Assets.FirstOrDefault();
                Console.WriteLine("asset name: {0}", asset?.Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + (ex.InnerException == null ? "" : ex.InnerException?.Message));
            }
            Console.WriteLine("hit any key");
            Console.ReadKey();
        }
    }
}

最初にToken取得用のCredentialsを作ります。その際にAzureの環境を指定(引数のazureEnvironment)するのですが、パブリックのAzureやChina、Germanyなどは定数で用意されているのでそちらを使います。Azure Stackなどの場合は自前で生成しましょう。またCloudMediaContextのコンストラクタに渡すapiServer(Media Servicesのエンドポイント)はAzureポータルより取得します。
API Accessというメニューがあると思うのでそちらから「Connect to Azure Media Services API with authentication (interactive)」を選択します。その中のREST API endpointの値を使います。(だいたい https://Media Services名.restv2.リージョン.media.azure.net/api/ になると思いますが)
※いちおうACS形式用のオーバーロードもまだあります。
imageimage

後は今まで通りですね。実行すると認証ダイアログが表示されてちゃんと認証すれば結果が得られると思います。
image

簡単ですね。

2. サービスプリンシパルの場合

次はサービスプリンシパルの場合です。先にコード見ておきましょう。

namespace mediaservicesample
{
    using System;
    using System.Linq;
    using Microsoft.WindowsAzure.MediaServices.Client;

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.Write("input your AzureAD tenant name: ");
                var tenantName = Console.ReadLine();
                Console.Write("input your media services endpoint: ");
                var endpoint = Console.ReadLine();
                Console.Write("input your client id: ");
                var clientId = Console.ReadLine();
                Console.Write("input your client secret: ");
                var clientSecret = Console.ReadLine();

                var tokenCredentials = new AzureAdTokenCredentials(
                                        tenant: tenantName, // Azure ADテナント名
                                        clientSymmetricKey: new AzureAdClientSymmetricKey(
                                            clientId: clientId,         // Service Principal の ClientID
                                            clientKey: clientSecret     // Service Principal の Secret
                                            ),
                                        azureEnvironment: AzureEnvironments.AzureCloudEnvironment
                                        );
                var tokenProvider = new AzureAdTokenProvider(tokenCredentials);
                var mediaContext = new CloudMediaContext(apiServer: new Uri(endpoint), // Media Services REST API エンドポイント
                                                        tokenProvider: tokenProvider
                                                        );

                var asset = mediaContext.Assets.FirstOrDefault();
                Console.WriteLine("asset name: {0}", asset?.Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + (ex.InnerException == null ? "" : ex.InnerException?.Message));
            }
            Console.WriteLine("hit any key");
            Console.ReadKey();
        }
    }
}

違いはAzureAdTokenCredentialsを作るときにSymmetricKeyを追加で渡してるだけです。(面倒な処理はSDKが勝手にやってくれます。実際の処理は普通のBearerトークン取得する場合と同じですが。)

さてコードの変更点が分かったところで、サービスプリンシパルを用意する必要があります。先ほどと同じようにMedia ServicesのAPI Accessから今度は「Connect to Azure Media Services API with service principal」を選択します。
image

その次のブレードで新規作成か既存のものを選ぶことができます。
image
新規作成の場合はアプリ名を入力して保存ボタンをクリックします。保存が終わったらサービスプリンシパルが追加されて構成を触れるようになります。
image
権限みるととりあえずAzure ADにサインインできてユーザープロファイルが参照できればいいだけのようですね。既存のものを使う場合は参考にしましょう。
image

さて肝心のクライアントIDなどはManage Applicationを選択して表示されるブレードから取得します。クライアントIDはApplication IDが該当します。
image
クライアントシークレットは「Keys」を選択して新しく追加しましょう。なおキーは保存時のみ参照できるので忘れずメモりましょう。
image
これで準備OKです。
実行してみるとちゃんと動くことがわかります。
image

ちなみにキーが間違ってたりすると認証エラーになります。(対話ログインの場合は401とかになる)
image

Tips

なおAzure ADで認証する際のユーザーやサービスプリンシパルはMedia ServicesにOwnerまたはContributorの権限が必要なようです。カスタムRBACは秋ぐらいに提供予定らしいですので注意。

また最新版のAzure Media Services ExplorerであればすでにAzure AD認証に対応しています。
image

認証の際のフローなど興味があるかたはFiddlerでパケットみるといいかと思います。(ちゃんとBearerトークン渡していることがわかります)
image

サービスプリンシパル使用時、クライアントシークレットを使っていますが証明書にも対応していますのでそちらを使うようにしてもいいですね。(たぶんそっちが推奨だったかと)
※ポータルからは証明書の管理ができないのが難点。

認証の詳細についてはこちらのドキュメントも参考に。

Conclusion

長々と書きましたが言うほど変更する箇所はないと思うので、さっさと対応してしまいましょうね。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中