以前に記事だけ取り上げましたけど勘違いしていたので改めて。
基本的には上記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形式用のオーバーロードもまだあります。
後は今まで通りですね。実行すると認証ダイアログが表示されてちゃんと認証すれば結果が得られると思います。
簡単ですね。
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」を選択します。
その次のブレードで新規作成か既存のものを選ぶことができます。
新規作成の場合はアプリ名を入力して保存ボタンをクリックします。保存が終わったらサービスプリンシパルが追加されて構成を触れるようになります。
権限みるととりあえずAzure ADにサインインできてユーザープロファイルが参照できればいいだけのようですね。既存のものを使う場合は参考にしましょう。
さて肝心のクライアントIDなどはManage Applicationを選択して表示されるブレードから取得します。クライアントIDはApplication IDが該当します。
クライアントシークレットは「Keys」を選択して新しく追加しましょう。なおキーは保存時のみ参照できるので忘れずメモりましょう。
これで準備OKです。
実行してみるとちゃんと動くことがわかります。
ちなみにキーが間違ってたりすると認証エラーになります。(対話ログインの場合は401とかになる)
Tips
なおAzure ADで認証する際のユーザーやサービスプリンシパルはMedia ServicesにOwnerまたはContributorの権限が必要なようです。カスタムRBACは秋ぐらいに提供予定らしいですので注意。
また最新版のAzure Media Services ExplorerであればすでにAzure AD認証に対応しています。
認証の際のフローなど興味があるかたはFiddlerでパケットみるといいかと思います。(ちゃんとBearerトークン渡していることがわかります)
サービスプリンシパル使用時、クライアントシークレットを使っていますが証明書にも対応していますのでそちらを使うようにしてもいいですね。(たぶんそっちが推奨だったかと)
※ポータルからは証明書の管理ができないのが難点。
認証の詳細についてはこちらのドキュメントも参考に。
Conclusion
長々と書きましたが言うほど変更する箇所はないと思うので、さっさと対応してしまいましょうね。