セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.55 サービスプリンシパルによる非対話型認証|Azure&Entra IDスクリプト大作戦(2)
2024年10月28日配信
執筆者:山内 和朗
前回(vol.54)は、Azure PowerShellの「対話型認証(Interactive authentication)」を含むスクリプトによる自動化を試しました。使用したユーザーは、Azureサブスクリプションの管理者(従来のサブスクリプション管理者やアカウント管理者、共同管理者、または同等のAzureのロールが割り当てられたユーザー)の資格情報です。現在、MicrosoftはAzureへのすべてのサインイン試行に対する多要素認証(MFA≪Multi-Factor Authentication≫)の必須化を段階的に進めており、この方法は使用できなくなります。そもそもMFAに関係なく、対話型認証のスクリプトによる自動化は非推奨とされています。この制約の解決策の1つが、「サービスプリンシパル」による「非対話型認証(Noninteractive authentication)」です。他にも「マネージドID」の方法がありますが、話がややこしくなるためここではサービスプリンシパルだけを取り上げます。
「サービスプリンシパル」は、Azureの通常のユーザー(ユーザープリンシパル)とは異なり、アプリケーションが使う資格情報のセットであり、MFAやAzureの条件付きアクセスの対象外です。Azureポータルへのサインインには使用できません。また、必要最小限のリソースに対するアクセス許可に制限することができます。今回は、サービスプリンシパルを作成して、「閲覧者」のアクセス許可だけを与え、非対話型認証によるスクリプト化に挑戦します。
サービス プリンシパルを使用して Azure PowerShell にサインインする|Auzre PowerShell(Microsoft Learn)
まず、サービスプリンシパルを作成します。「Microsoft Entra管理センター」(https://entra.microsoft.com/)にAzureの管理者としてサインインし、「ID > アプリケーション > アプリの登録」を開いて、「+新規登録」をクリックします。「名前」に分かりやすい表示名を入力し、「サポートされているアカウントの種類」で「この組織ディレクトリのみに含まれるアカウント(<ディレクトリ名> のみ - シングル テナント)」を選択し、「登録」をクリックします(画面1)。「リダイレクトURI」の指定は不要です。ポータルでは「アプリケーション」や「アプリ」という表現で分かり難いですが、これがサービスプリンシパルになります。
画面1 「Microsoft Entra管理センター」でアプリケーションを登録する。これがサービスプリンシパルになる
次に、サービスプリンシパルの認証方法を決め、資格情報を準備します。サービスプリンシパルは、パスワードベースの認証と証明書ベースの認証をサポートしています。今回は、より簡単に実装できる(できそうな、私も初めてやっていることなので詳しくはありません)、パスワードベースの認証にしたいと思います。「ID > アプリケーション > アプリの登録」を開き、先ほど作成したアプリケーションを開いて、「証明書とシークレット」を開き、「+新しいクライアント シークレット」をクリックして、有効期限(180日、90日、365日、545日、730日、またはカスタム)を選択し、シークレットを追加します。シークレットを追加したら、別のページに移動する前に「値」の横にある「クリップボードにコピー」をクリックして、作成されたシークレットの値を控えておきます(画面2)。このシークレットの値がサービスプリンシパルの「パスワード」に相当します。別のページに移動してしまうと、値のコピーができなくなるので注意してください。その場合、クライアントシークレットを再作成する必要があります。
画面2 サービスプリンシパルにクライアントシークレットを追加し、その「値」(サービスプリンシパルのパスワード)をコピーして控えておく
アプリケーションの「概要」ページに移動し、「基本」にある「アプリケーション(クライアント)ID」についても、「クリップボードにコピー」をクリックして控えておきます(画面3)。この「アプリケーション(クライアント)ID」が、サービスプリンシパルの「ユーザー名」に相当します。
画面3 アプリケーションの「概要」ページからアプリケーション(クライアント)ID」をコピーして控えておく
最後に、サービスプリンシパルに対して、Azureへのアクセス権限を付与します。Azureポータル(https://portal.azure.com/)にAzureの管理者としてサインインし、アクセスを許可するリソースの「アクセス制御(IAM)」を開いて、「+追加 > ロールの割り当ての追加」をクリックして、作成したサービスアカウントに対して「閲覧者」のロールを割り当てます。例えば、Azureサブスクリプションのすべてのリソースに対して「閲覧者」の権限を付与するには、「サブスクリプション」レベルでロールを割り当てます(画面4)。最小限の権限にするには、リソースごとにロールを設定してください。
画面4 サブスクリプションレベルで「閲覧者」ロールの権限をサービスプリンシパルに割り当てる。より厳格に制限したい場合は、リソースごとに設定すればよい
サービスプリンシパルを作成し、資格情報の準備と、アクセス許可の設定が終わったら、次のようにスクリプトを記述することで、サービスプリンシパルによる非対話型認証とAzure PowerShellの任意のコマンドレットの実行を自動化することができます(画面5)。サービスプリンシパルを使用する場合、Connect-AzAccountを実行する際に、-TenantパラメーターによるテナントIDの指定が必須となります。Azure PowerShellでは、テナントIDやサブスクリプションIDの指定が必要な場合があります。テナントIDはMicrosoft Entra管理センターのアプリケーションの「概要」ページなどから、サブスクリプションIDはAzureポータルのサブスクリプションの「概要」ページなどからコピーすることができます。
$tenantid = "テナントID" $password = ConvertTo-SecureString "クライアントシークレットの値" -AsPlainText -Force $username = "アプリケーション (クライアント) ID" $cred = New-Object System.Management.Automation.PSCredential($username, $password) Connect-AzAccount -ServicePrincipal -Credential $cred -Tenant $tenantid #Azure PowerShellの任意のコマンドレット(Get-AzVMなど)をここで実行 # 切断 Disconnect-AzAccount |
(プレーンテキストで表示)
画面5 サービスプリンシパルを使用したAzure PowerShellのスクリプト化例
パスワード(クライアントシークレットの値)をスクリプトに埋め込みたくないという場合は、暗号化された標準文字列に変換してテキストファイルに保存し、そこからセキュリティで保護された文字列(System.Secure.SecureString)を取り出して使用することができます(画面6)。その方法については、前回説明しました。
画面6 パスワード(クライアントシークレットの値)を暗号化された標準文字列に変換してテキストファイルに保存し、そこからセキュリティで保護された文字列を取り出して使用する例
Azure PowerShellを使用するには、ローカルコンピューター(Windows、Linux、またはmacOS)にAzure PowerShellモジュールをインストールする必要があります。インストールには多少時間がかかりますし、更新バージョンがリリースされたら更新作業が必要です。今回は説明していませんが、Azure CLI(コマンドラインインターフェイス)を使用する場合も同様です。「Azure Cloud Shell(https://shell.azure.com/)」を使用すれば自動ログインでき、最新バージョンのAzure PowerShellやAzure CLIをいつでも使用できますが、「Azure Cloud Shell」はWebブラウザー経由の対話操作であり、ローカルスクリプトによる自動化には使用できません。
Azure PowerShellを使用せずに、Azureからリソースの情報を取得する、それには「Azure REST API」を使用する方法があります。Azure REST APIであれば、PowerShellの「Invoke-WebResuest」や「Invoke-RestMethod」、「curl」(Windows 10バージョン1803以降とWindows Server 2019以降にはC:¥Windows¥System32¥curl.exeがOSに標準で付属しています)、あるいは独自に開発したアプリケーションから、Azureのリソース情報を取得することができそうです。次回、いよいよ本題のREST APIの世界に足を踏み入れます。今回作成したサービスプリンシパルは、そのままAzure REST APIでも利用する予定です。
Azure REST API リファレンス|Azure(Microsoft Learn)