【Microsoft Azure】AzureリソースのマネージドIDを理解する

こんにちは。今日は、Microsoft Azureに登場する”マネージドID”という概念について理解を深めるために、調べてみて分かったことを備忘も兼ねてまとめておこうと思います。

今回の記事は、Microsoft公式ドキュメントを大いに参考にさせていただいております。Microsoft Azureはドキュメントが非常に充実しているので、詳細を知りたい方はこちらも併せてご覧ください!

マネージドIDが必要になる背景

  • クラウド アプリケーションの構築時における一般的な課題は、クラウド サービスへの認証用のコードで資格情報をどのように管理するかである
  • 資格情報は開発者のワークステーションに表示されないこと、またソース管理にチェックインされないことが理想
  • 資格情報やシークレットなど、各種キーを安全に保管する手段としては Azure Key Vault があるが、それらを取得するためには、コードから Key Vault に対して認証を行わなければならない
  • この問題を解決するのが、Azure Active Directory (Azure AD) の Azure リソースのマネージド ID 機能

マネージドIDとは?

  • Azure AD で自動的に管理される ID を Azure サービスに提供する機能
  • この ID を使用すれば、コードに資格情報を追加しなくても、Azure AD の認証をサポートするさまざまなサービス (Key Vault を含む) に対して認証を行うことができる
  • マネージドIDには、”システム割り当てマネージドID”と、”ユーザ割り当てマネージドID”の2種類がある

マネージドIDを利用してリソースにアクセスする仕組み

ここでは、マネージドIDを利用してVMに接続する際の動作を説明します。

マネージドIDを理解する上での登場人物
  • サービスプリンシパル:Azure AD側の概念。単一のテナントまたはディレクトリ内のグローバル アプリケーション オブジェクトのローカル表現、つまりアプリケーション インスタンス(公式Docより引用だが、触ったことがないのでちょっと何のこといってるのかよくわからない・・後述)
  • クライアントID:Azure ADによって生成される一意識別子
  • プリンシパルID:マネージドIDに対するサービスプリンシパルオブジェクトのオブジェクトID。AzureリソースへのRBAC(ロールベースアクセス制御)付与に利用される。
  • Azure Instance Metadata Service (IMDS):Azure Resource Manager を使用して作成されたすべての IaaS VM にアクセスできる REST エンドポイント

以下の図は、公式ドキュメントで紹介されているものになります。

公式ドキュメントより
  1. Azure Resource Manager は、VM 上でシステム割り当てマネージド ID を有効にするための要求を受け取ります。
  2. Azure Resource Manager は、VM の ID を表すサービス プリンシパルを Azure AD に作成します。 このサブスクリプションによって信頼されている Azure AD テナントに、サービス プリンシパルが作成されます。
  3. Azure Resource Manager では、Azure Instance Metadata Service の ID エンドポイントをサービス プリンシパルのクライアント ID と証明書を使用して更新することによって、VM 上に ID が構成されます。
  4. VM に ID が設定された後、Azure リソースにアクセスする権利を VM に与えるには、そのサービス プリンシパル情報を使用します。 Azure Resource Manager を呼び出すには、Azure AD のロールベースのアクセス制御 (RBAC) を使用して、VM のサービス プリンシパルに適切なロールを割り当てます。 Key Vault を呼び出すには、Key Vault 内の特定のシークレットまたは特定のキーにアクセスする権利をコードに与えます。
  5. VM 上で実行されているコードは、VM 内からのみアクセスできる Azure Instance Metadata サービス エンドポイントにトークン (http://169.254.169.254/metadata/identity/oauth2/token) を要求できます。
    • リソース パラメーターは、トークンの送信先のサービスを指定します。 Azure Resource Manager に対して認証を行うには、resource=https://management.azure.com/ を使用します。
    • API バージョン パラメーターは、IMDS バージョンを指定します。api-version=2018-02-01 以降を使用してください。
  6. 手順 3. で構成したクライアント ID と証明書を使用して、手順 5. で指定したアクセス トークンを要求する呼び出しが Azure AD に対して行われます。 Azure AD は、JSON Web トークン (JWT) アクセス トークンを返します。
  7. コードは、Azure AD 認証をサポートするサービスへの呼び出しでアクセス トークンを送信します。

[デモ] VMからAzure StorageアカウントにマネージドIDで接続する

ものは試し。こちらのドキュメントで紹介されていたチュートリアルを実施してみることで、理解を深めていきたいと思います。

シナリオは、Azure StorageアカウントにマネージドIDを利用して接続するというもの。

それではさっそくやってみます!

仮想マシンの作成 & システム割り当てマネージドIDの発行

はじめに、仮想マシンを作成します。特別な設定はしていません。(安いリソースを使っています)

*後で気付いたのですが、公式ドキュメントのチュートリアルは.NET Frameworkでコードをかいているので、Windows OSにしておくべきです。

仮想マシンの作成
システム割り当てマネージドIDの発行

ストレージアカウント&Blobコンテナの作成

次に、適当なストレージアカウントを作成します。(特に特別な設定はしていません)

続けて、そのストレージアカウント上に、Blobコンテナを作成します。

続けて、Blobコンテナにアップロードするサンプルファイルを作成します。ローカルでHelloWorld.txtファイルを作成して、Blobコンテナにアップロードします。

これでStorageアカウント側のリソース準備は完了です。続けてアクセス権の設定に進みます。

ストレージアカウントへのアクセス権の付与

ストレージアカウントのブレードに戻り、アクセス制御>追加>ロール割り当ての追加へ進みます。

ロール割り当ての追加では、以下を選択します。

  • 役割:ストレージBLOBデータ閲覧者
  • アクセスの割り当て先:仮想マシン
  • 先ほど作成したVMが一覧に表示されるので、選択
ストレージアカウントへのアクセス制御の追加
アクセス制御付与に成功したことの確認

これで必要な設定が完了しました。続けて、データへのアクセスを試してみます。

VMからBlob Storageデータへのアクセス

すみません、これは試してみたんですがWindowsAzureパッケージが見つからない状態が解消できずどうしてもうまくいきませんでした・・・(公式ドキュメントの説明ここだけ雑すぎる・・・)

想定では、以下のコードを実行すると、Blobに格納したファイルの中身が表示されるようです。

*以下コードの<URI to blob file>は、自分の環境のBlobファイルパスに変更します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Web.Script.Serialization;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

namespace StorageOAuthToken
{
    class Program
    {
        static void Main(string[] args)
        {
            //get token
            string accessToken = GetMSIToken("https://storage.azure.com/");

            //create token credential
            TokenCredential tokenCredential = new TokenCredential(accessToken);

            //create storage credentials
            StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);

            Uri blobAddress = new Uri("<URI to blob file>");

            //create block blob using storage credentials
            CloudBlockBlob blob = new CloudBlockBlob(blobAddress, storageCredentials);

            //retrieve blob contents
            Console.WriteLine(blob.DownloadText());
            Console.ReadLine();
        }

        static string GetMSIToken(string resourceID)
        {
            string accessToken = string.Empty;
            // Build request to acquire MSI token
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=" + resourceID);
            request.Headers["Metadata"] = "true";
            request.Method = "GET";

            try
            {
                // Call /token endpoint
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                // Pipe response Stream to a StreamReader, and extract access token
                StreamReader streamResponse = new StreamReader(response.GetResponseStream());
                string stringResponse = streamResponse.ReadToEnd();
                JavaScriptSerializer j = new JavaScriptSerializer();
                Dictionary<string, string> list = (Dictionary<string, string>)j.Deserialize(stringResponse, typeof(Dictionary<string, string>));
                accessToken = list["access_token"];
                return accessToken;
            }
            catch (Exception e)
            {
                string errorText = String.Format("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
                return accessToken;
            }
        }
    }
}

以下のコードで、Storageへのアクセストークンを取得することができます。

  • (HttpWebRequest)WebRequest.Create(“http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=” + resourceID)で接続している169.254.169.254が、上でご紹介したAzure Instance Metadata Service (IMDS)のアドレスになる

[参考] 仮想マシン以外のリソースでマネージドIDを利用する

先ほどの例では、IaaSのVMとStorageの接続をマネージドIDを介して行いました。

IaaS VM以外のリソースでマネージドIDを有効化する手順も先ほどと変わりません。

以下はApp Serviceの例ですが、同様にIDブレードからマネージドIDを有効化可能です。

まだまだいろいろな接続パターンはあって試してみたかったのですが、ちょっと力尽きたので今日はここまで・・・

本日も最後まで御覧いただきありがとうございました!

+1

この記事を気に入っていただけたらシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。

ABOUT US

アバター
Yuu113
初めまして。Yuu113と申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。