AzureのマネージドIDを分かりやすく解説する。実装サンプルあり

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

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

Contents

マネージドIDとは?

  • Azure AD による認証をサポートしたリソースに接続する際に使用する IDをアプリケーションに付与する機能
  • この ID を使用すれば、コードに資格情報をハードコードしなくても、Azure AD の認証をサポートするさまざまなサービス (Key Vault を含む) に対して認証を行うことができる(=Azure ADの認証トークンを取得することができる)
  • マネージドIDの実体は、特殊なサービスプリンシパル。
  • マネージドIDには、”システム割り当てマネージドID”と、”ユーザ割り当てマネージドID”の2種類がある

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

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

マネージドIDを使うと嬉しいこと

  • アプリケーションコードに資格情報(ユーザ名・パスワードの組み合わせ)を含める必要がなくなるので、セキュリティが向上する
  • アプリケーションに付与されるIDの資格情報を自ら管理する必要がないので管理負荷も軽減
  • 独自のアプリケーションを含む、Azure AD 認証をサポートするあらゆるリソースに対して認証を行うことができる
  • 追加コストは一切かからない

マネージドIDの利用シナリオの例

いろいろ考えられますが、ほんの一例として自分がやったことあるのは以下です。

  • Azure VM/Azure App Service上のアプリからAzure Storageに接続する
  • Azure VM/Azure App Service上のアプリからAzure SQL Databaseに接続する
  • Azure VM/Azure App Service上のアプリからAzure Key Vaultに接続する

これらのデータサービスに接続する際、通常は資格情報を含んだ接続文字列を使って接続すると思いますが、マネージドIDを利用することで、資格情報を含まない形で接続できるようになります。

マネージドIDの種類

マネージドIDには、以下の2種類があります。

  • システム割り当てマネージドID
  • ユーザ割り当てマネージドID

共通すること、違うことは以下にまとめられています。

https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/overview#managed-identity-types

マネージド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)のアドレスになる

[実践] その他のシナリオ

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

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

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

App ServiceとAzure SQL Databaseの接続にマネージドIDを利用した実装サンプルはこちらにまとめています。

あとは、App Service/FunctionsからマネージドIDを使ってKey Vaultに接続した話はこちらに。

ご参考になりましたら幸いです。

以上、マネージドIDの概要まとめでした!

本日も最後まで御覧いただきありがとうございました!本記事が少しでもお役に立ちましたら、下のいいねボタンをポチって頂けると励みになります!

おしまい

(おまけ)Azureをもっと知りたい方には

Azureの認定資格を取得する

Azureは、資格試験が充実していますのでご興味のあるところから勉強してみてはいかがでしょうか。こちらに一覧と勉強方法などをまとめましたので、参考になりましたら幸いです。

書籍で勉強する

Azure関連書籍、ひと昔はとても少なかったのですが、少しづつ増えてきている印象です。以下がおすすめです。

オンラインコンテンツを活用する

個人的には最近はUdemyなどのオンライン学習コンテンツもおすすめです。Udemyの場合は、30日間の無料返金期間もあるので、購入してちょっと違ったなと思ったら返金できるところも安心で、私も活用しています。

Azureについては、日本語コンテンツも増えてきているので、以下に特に評価が高いものをのせておきます。

作りながら覚えるMicrosoft Azure入門講座(PaaS編)

作りながら覚えるMicrosoft Azure入門講座(IaaS編)

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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

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