【さらばパスワード】簡単すぎるAzure マネージド ID によるログイン

【さらばパスワード】簡単すぎるAzure マネージド ID によるログイン

こんにちは!やましー@データ活用クラウドエンジニア(@yamashi18041)です!

今日は Microsoft Azure のマネージド ID 機能が凄かったので解説したいと思います。

不正アクセス、情報情報流出などセキュリティ事故が後を絶たない昨今、ますます企業にとってセキュリティへの関心は高まるばかりです。

そんな中、開発の現場においてもシステムを堅牢に保つ設計は必須であり、エンジニアのスキルとしても欠かせないものとなっています。

しかし、システムのセキュリティ強度を高めれば高めるほど利便性は失われそのバランスを取るのは非常に難しいことと思います。

今回、紹介したいのはその利便性とセキュリティ強度を共に高めるのに有効なAzure リソース マネージドIDについて解説したいと思います。

私が担当するお客様は非常にセキュリティについてシビアなのですが、この機能を提案し導入することで、お客様に喜んでもらえることができました。

パスワード管理や認証方式など必須スキルであるにも関わらずあまり面白みがなく難しいのでエンジニアは避けて通りがちな分野です。

しかし逆を言えばこのスキルもっているエンジニアは希少価値が高いともいえます。

この記事を読むことであなたはAzureにおけるパスワードや証明書の管理をどのように行えばよいかというのが分かります。

そしてエンジニアとしての市場価値は上がります。

逆にこの記事を読まなかったことであなたが作ったシステムのパスワードが流出し機密情報が洩れるかもしれません。

その結果会社は対応に追われ多額の賠償金を請求され、当事者であるあなたはその責任を取らされ、家庭は崩壊。最悪の未来が待っているかもしれません。

それほどまで現在のセキュリティへの対応は慎重にならなければならないです。

そうならないためにもぜひマネージドID機能について理解していただければと思います。

この記事は以下のような方を想定しています。

  • Azureを使っているシステムエンジニア
  • どのようなセキュリティリスクを解消できるか知りたい
  • パスワードや証明書による認証に不安を抱いている
  • マネージドIDの使い方を知りたい

それでは解説していきます。

Azure リソース マネージドIDとは

Azure リソース マネージドIDについて簡単に説明したいと思います。

一言で言うならば「パスワードなしでAzure ADにログイン可能なリソースのID」です。

この機能を使わない場合、Azureにログインしてリソースを操作するためにはサービスプリンシパルと呼ばれるアプリケーションの為のIDとパスワード(または証明書)を作成し、それによってログインする必要があります。

夜間バッチ等の定時に自動で動かすスクリプトを作った場合、そのパスワードや証明書情報をコードに埋め込んでログインさせるしかありません。

しかしそんなことをしてしまうと、サーバーを利用する一般ユーザーや、コード管理用のリポジトリを使用する人にパスワードを知られてしまうリスクがあります。

そこでその問題を解決するのがこのマネージドID機能というわけです。

公式はドキュメントサイトはこちら
https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/overview

マネージドIDの具体的な例

Azure 仮想マシンのマネージドIDを例にして具体的に説明してみます。

例えばAzureの仮想マシン(VM01)のマネージドIDを有効にしたとします。

するとVM01からのみAzure ADへのログインが可能になります。

ログインすることでVM01はAzureのリソースに対してPowaerShellやAzコマンドなどから制御を行うことができます。

そして、マネージドIDを有効にしたVM01に対してRBAC(ロールベースアクセスコントロール)を行うことができるようになり、VM01から制御可能なAzure内のリソースの範囲を絞ったり、権限をコントロール出ます。

マネージドIDのRBACによる権限制御

仮に悪意のあるユーザにVM01が操作されたとしても被害を最小限に止めることができます。

マネージドIDを有効にすると、Azureの内部的にはVM01君というユーザーをAzure ADに作っているような感じです。

この機能の素晴らしいところは3点だと思います。

  • パスワードや証明書の管理が不要
  • 有効にした仮想マシンからのみログインが可能
  • 仮想マシンに付与する権限を細かく制御が可能

マネージドIDの種類

マネージドIDには2種類あります。

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

要件に合わせてどちらかを選択することになるかと思います。

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

システム割り割り当てマネージドIDとは、

リソース(VM01など)に対してマネージドID機能を有効にしたときにAzure(システム)によってそのリソースにIDが割り当てられます。

このIDを使ってログインや権限のコントロールを行うことができます。

IDの発行は有効にするだけなので非常に簡単です。

たくさんのリソースのマネージドIDを扱わない場合はこちらで十分だと思います。

ユーザー割り当てマネージド ID

マネージドIDそのものをユーザー自身が作成します。この時点ではまだどのリソースにもそのIDは割り当たっていません。

そこで作成したマネージドIDをユーザーがリソース(VM01など)に対して割り当てる操作を行います。

作成したIDを使ってログインや権限のコントロールを行うのはシステム割り当てマネージドIDと同じです。

違いは1つのマネージドIDを複数のリソースに割り当てることが可能という点です。

イメージとしてはロール(役割)ごとに発行すると考えればよいかと思います。

多くのリソースでマネージドIDを使いたい場合はこちらの方がオペレーションや管理が楽になると思います。

システム割り当てとユーザー割り当てマネージドIDの比較

項目システム割り当てユーザー割り当て
ID対リソースの紐づけ一対一一対多
リソースが消えたときIDも消えるIDは消えない
適用規模小規模向け大規模向け

マネージドIDの仕組み

具体的にどのような仕組みになっているか解説したいと思います。

ある程度どのような仕組みでセキュリティが担保されているのか理解しておかないとお客様に質問されたときに的確に回答することができません。

仮想マシンのシステム割り当てマネージドIDを例に説明します。

仮想マシンの中で動作するアプリケーションやスクリプトがAzureにログインする際に必要になる情報は2つ。

「オブジェクトID」と「トークン」です。

  • オブジェクトIDとは
    その仮想マシン固有のIDで自分自身を証明するためのIDです。
  • トークンとは
    Azure上の仮想マシンがAzureに対して要求して取得する印(文字列)です。

この二つの情報を合わせてログインに使用します。

仮想マシンのマネージドID機能を有効にすると、オブジェクトIDが発行されます。

この時、内部的にサービスプリンシパルが作られます。

そしてマネージドIDを有効にした仮想マシンの中で「curl」や「Invoke-WebRequest」を使ってAzureの Instance Metadata サービス エンドポイント からトークンを取得できるようになります。

curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -H Metadata:true   
Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -Method GET -Headers @{Metadata="true"}

ここで特筆すべき点はトークンを取得するためにアクセスするアドレスです。

取得先のアドレスとして「 169.254.169.254 」を指定します。

ネットワークに詳しい方ならご存知かと思いますが、169.254から始まるアドレスはリンクローカルアドレスと言ってルーティングされないアドレスなのです。

要するに絶対にインターネットから入ってくることも逆にインターネットへ出ていくこともできないアドレスを使用してトークンを取得しているので非常にセキュアだと言えます。

さらに、マネージドIDを有効にしていない場合はトークンは取得できないこともセキュリティを高めている要素の1つと言えると思います。

オブジェクトIDとトークンを取得できるようになったならば、それらを使ってAzureにログインするコマンドを実行すればログインができてしまうという仕組みです。

Connect-AzAccount -AccessToken <String> -AccountId <String>

マネージドIDをサポートするサービスと認証をサポートするサービス

マネージドID機能を有効にできたり、それによって認証を受けるサービスは限られていて今後も増えること予想されます。

2020年2月25日現在の情報をまとめておきます。

最新情報はMicrosoftの公式から参照をお願いします。

https://docs.microsoft.com/ja-jp/azure/active-directory/managed-identities-azure-resources/services-support-managed-identities

本記事の例で取り上げているサービスは

  • マネージドIDをサポートするリソース:Azure Virtual Machines
  • 認証をサポートするサービス :Azure Resource Manager

です。

マネージドIDをサポートするサービス

  • Azure Virtual Machines
  • Azure 仮想マシン スケール セット
  • Azure App Service
  • Azure Blueprint
  • Azure Functions
  • Azure Logic Apps
  • Azure Data Factory V2
  • Azure API Management
  • Azure Container Instances
  • Azure Container Registry タスク
  • Azure Service Fabric
  • Azure Kubernetes Service

認証をサポートするサービス

  • Azure Resource Manager
  • Azure Key Vault
  • Azure Data Lake
  • Azure SQL
  • Azure Event Hubs
  • Azure Service Bus
  • Azure Storage の BLOB とキュー
  • Azure Analysis Services

応用例

応用例として Azure Key Vault(キーコンテナ) へのアクセスをマネージドIDを使う方法があります。

Azure 以外のサービスと連携する場合はどうしてもID、パスワード、証明書を使わざるを得ないことが出てくると思います。

その場合はID、パスワード、証明書をKey Vaultに保存して置き、マネージドIDを使ってKey Vaultから取り出すという運用をすることができます。

実際にAzure マネージドIDを使ってみる

実際どのように操作をするか使ってみたいと思います。

今回は仮想マシンからPoawerShellを使ってAzure Data Factoryのパイプラインを実行してみます。

概要

  1. Windows仮想マシン(YMSTVM01)のシステム割り当てマネージドIDを有効にする
  2. 仮想マシンにDataFactoryの共同作成者のロールを割り当てる
  3. 仮想マシンからPoawerShellを使ってAzureにログインする
  4. Azure DataFactoryのパイプラインを実行する

Windows仮想マシン(YMSTVM01)のシステム割り当てマネージドIDを有効にする

① 「Virtual Machines」を選択します。

② 有効にしたい仮想マシン「YMSTVM01」を選択します。

③ IDを選択します。

① 「オン」を選択します。

② 保存を選択します。

① 「はい」を選択します。

① マネージドIDが有効になり、オブジェクトIDが発行されます。

仮想マシンにDataFactoryの共同作成者のロールを割り当てる

今回はデータファクトリリソースのパイプラインを実行を行うため、Data Factoryの共同作成者ロールを付与します。

① 「データファクトリ」を選択します。

② 捜査対象のデータファクトリ「ymst-factory01」を選択します。

① 「アクセス制御(IAM)」を選択します。

② ロールの割り当てを追加するの「追加」を選択します。

① 役割は「Data Factory共同作成者」を選択します。

②  「仮想マシン」を選択します。

③ 選択にマネージドIDを有効にした仮想マシン「YMSTVM01」を入力します。

④ 表示された仮想マシンを選択します。選択すると選択したメンバーに移動します。

⑤保存を選択します。

仮想マシンに付与された権限を確認する

① 「Virtual Machines」を選択します。

② 権限を確認したい仮想マシン「YMSTVM01」を選択します。

③ 「ID」を選択します。

① 「このマネージドIDに割り当てられた Azure RBAC ロールを表示します」を選択する。

仮想マシンに割り当てられた役割を一覧として確認することができます。

仮想マシンからPoawerShellを使ってAzureにログインする

今回はPowerShellのAzモジュールを使ったログインを試してみたいと思います。

AzureRMモジュールやAzureCLI(azコマンド)など様々な方法でAzureを操作することができますが、やり方は基本的に同じです。

まずはサーバーにリモートデスクトップで接続します。

Azモジュールインストールする

既にインストール済みである場合は不要です。

Azモジュールをインストールをしていない場合はPowershellを起動しインストールします。

Install-Module -Name Az -AllowClobber -Scope AllUsers

詳しいインストールの方法はこちら

https://docs.microsoft.com/ja-jp/powershell/azure/install-az-ps?view=azps-3.5.0

アクセストークン取得する

アクセストークンを取得するためWEBリクエスト実行します。

$response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -Headers @{Metadata="true"}

レスポンスからアクセストークンを取り出します。

$AccessToken = ($response.Content | ConvertFrom-Json).access_token

ログインする

取り出したアクセストークンを-AccessTokenに指定し、portalで有効にしたオブジェクトIDを-AccountId に指定してログインを実行します。

Connect-AzAccount -AccessToken $AccessToken -AccountId 79e394b5-98e4-4624-9d9d-74e953fd2b4a

これでログインができました。

ログイン失敗

マネージドIDが有効になってない場合はWEBリクエストで失敗し以下のような例外エラーがでます。

Invoke-WebRequest : {"error":"invalid_request","error_description":"Identity not found"}
発生場所 行:1 文字:13
+ $response = Invoke-WebRequest -Uri 'http://169.254.169.254/metadata/i ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest)
[Invoke-WebRequest]、WebExce    ption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Azure DataFactoryのパイプラインを実行する

ログインできたので実行データファクトリのパイプラインを実行してみます。

Azure DataFactoryのパイプラインを作成する

実行するためのパイプラインは事前に作成しておきます。

パイプラインの作成方法は以前書いた記事を確認いただければと思います。

https://ymstech.net/blog/how-to-get-data-with-azure-data-factory/#Azure_Data_Factory-2

PowerShellからパイプラインを実行する

$DataFactoryName = "ymst-factory01"
$ResourceGroupName = "YMST"
$PipeLineName = "pipeline1"
$Parameter = @{param1="HogeHoge"; param2="fugafuga"}


$RunID = Invoke-AzDataFactoryV2Pipeline `
    -DataFactoryName $DataFactoryName `
    -ResourceGroupName $ResourceGroupName `
    -PipelineName $PipeLineName `
    -Parameter $Parameter

実行結果を確認してみます。

$Run = Get-AzDataFactoryV2PipelineRun `
    -ResourceGroupName $ResourceGroupName `
    -DataFactoryName $DataFactoryName `
    -PipelineRunId $RunId

Write-output $Run

ResourceGroupName : YMST
DataFactoryName   : ymst-factory01
RunId             : d2043e87-35be-4f65-975b-7d7e5793591a
PipelineName      : pipeline1
LastUpdated       : 2/29/2020 1:51:02 PM
Parameters        : {[param1, HogeHoge], [param2, fugafuga]}
RunStart          : 2/29/2020 1:51:01 PM
RunEnd            : 2/29/2020 1:51:02 PM
DurationInMs      : 1431
Status            : Succeeded
Message           :

Statusが「Succeeded」となっていることを確認できました。

PowerShellからパイプラインで実行エラー

Azure Data Factoryにアクセス権を付与していない場合は以下のようなエラーがでるので、適切にアクセス権を設定して下さい

PS C:\> $RunID = Invoke-AzDataFactoryV2Pipeline `
>>     -DataFactoryName $DataFactoryName `
>>     -ResourceGroupName $ResourceGroupName `
>>     -PipelineName $PipeLineName `
>>     -Parameter $Parameter
Invoke-AzDataFactoryV2Pipeline : HTTP Status Code: Forbidden
Error Code: AuthorizationFailed
Error Message: The client 'bc3b7f04-1c7e-4306-bbfb-7064373a8fa0' with object id 'bc3b7f04-1c7e-4306-bbfb-7064373a8fa0' does not have authorization to perform action
'Microsoft.DataFactory/factories/pipelines/createRun/action' over scope
'/subscriptions/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/resourceGroups/YMST/providers/Microsoft.DataFactory/factories/ymst-factory01/pipelines/pipeline1' or the scope is invalid. If access was recently granted,
please refresh your credentials.
Request Id: cc01c017-adf7-404c-abae-0d6e59c14693
Timestamp (Utc):02/29/2020 14:30:01
At line:1 char:10
+ $RunID = Invoke-AzDataFactoryV2Pipeline `
+          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Invoke-AzDataFactoryV2Pipeline], CloudException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.DataFactoryV2.InvokeAzureDataFactoryPipelineCommand

またはこのようなエラーを返す場合もあります。

Invoke-AzDataFactoryV2Pipeline : Object reference not set to an instance of an object.
At C:\Users\masashi.yamashita\Desktop\datafactory.ps1:12 char:10
+ $RunID = Invoke-AzDataFactoryV2Pipeline `
+          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Invoke-AzDataFactoryV2Pipeline], NullReferenceException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.DataFactoryV2.InvokeAzureDataFactoryPipelineCommand

まとめ

今回マネージドIDについて解説&実際に使ってみました。

マネージドIDとは パスワードなしでAzure ADにログイン可能なリソースのID のことで、システムのセキュリティー強度を高めることができるサービスです。

マネージドIDは2種類あります。

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

仕組みとしてはオブジェクトIDとアクセストークンを合わせてログインすることでセキュアにログインができます。

アクセストークンの取得はマネージドIDを有効にした仮想マシンからしか取得することができないため非常にセキュアにシステムを保つことができることが分かりました。

パスワード流出リスクに限らず、様々なセキュリティーリスクがある中、常にその対策はアップデートされています。

エンジニアとしてしっかりとキャッチアップを図り、ライバルたちと差をつけていきたいところですね。

最後まで読んでいただきありがとうございました。

以上、やましー@データ活用クラウドエンジニア(@yamashi18041)でした。