サービスプリンシパルで完全自動化 ─ パスワードと証明書、2つの認証パターン
この記事の内容
- サービスプリンシパルを使ってユーザーの介在なしにAzureの処理を完全自動化する方法を解説します
- Microsoft Entra ID(旧Azure AD)でアプリケーション登録とサービスプリンシパル作成の関係を理解します
- パスワードベース(クライアントシークレット)の認証手順をPowerShellで実践します
- 証明書ベースの認証手順と、なぜ本番環境では証明書を使うべきかを説明します
Connect-AzAccountでサービスプリンシパルとして認証する具体的なコマンドを紹介します
はじめに
このシリーズはAzureの処理を自動化したい方を対象にしています。「対話的な認証を省いてスクリプトを完全自動化したい」「でもパスワードをスクリプトに直書きするのは怖い」という方にぴったりの内容です。
今回は第3回として、ユーザーが一切介在しない完全自動化を実現するサービスプリンシパル認証を取り上げます。
サービスプリンシパルとは
サービスプリンシパルとは、ユーザーではなくアプリケーションやスクリプトが使うためのIDです。サービスプリンシパルはMicrosoft Entra IDに対して資格情報を提出してトークンを取得し、そのトークンを使ってAzureのAPIを叩きます。
認証の流れは次のとおりです。
- サービスプリンシパルがEntra IDへ資格情報を提出
- 認証が通ればトークンを受け取る
- トークンを使ってAzure APIを呼び出す
今回はこの「資格情報」として、パスワードベース(クライアントシークレット) と 証明書ベース の2パターンを紹介します。
アプリケーション登録とサービスプリンシパルの関係
Entra IDでサービスプリンシパルを使うには、まずアプリケーション登録を行います。ここで少し混乱しやすいポイントがあります。
アプリケーション登録(「アプリの登録」)を作成すると、裏側でエンタープライズアプリケーション(=サービスプリンシパル)も自動的に作成されます。
| 画面 | 意味 |
|---|---|
| アプリの登録 | アプリケーションの定義(クラスに相当) |
| エンタープライズアプリケーション | サービスプリンシパルのインスタンス(オブジェクトに相当) |
プログラミングになじみのある方は「クラスとインスタンス」の関係で捉えると理解しやすいです。両者は同じアプリケーションIDを共有していますが、オブジェクトIDはそれぞれ異なります。
事前準備:アプリケーション登録とRBAC権限の付与
アプリケーションを登録する
- Azureポータルで「Microsoft Entra ID」を開きます
- 「アプリの登録」→「新規登録」を選択します
- 名前を入力します(例:
service-sp) - 「サポートされているアカウントの種類」はWebアプリを作らない場合は変更不要です
- リダイレクトURIも今回は不要なので空のまま「登録」します
登録後に表示されるアプリケーション(クライアント)ID と ディレクトリ(テナント)ID は後で使用しますので控えておいてください。
サービスプリンシパルにRBAC権限を付与する
サービスプリンシパルがリソースグループを作成できるよう、Azureサブスクリプションで権限を付与します。
- Azureポータルで「サブスクリプション」を開きます
- 対象のサブスクリプションを選択し「アクセス制御(IAM)」を開きます
- 「追加」→「ロールの割り当ての追加」を選択します
- ロールとして「共同作成者」を選択します
- 「メンバーの選択」でアクセスの割り当て先を「ユーザー、グループ、またはサービスプリンシパル」にします
- 作成したサービスプリンシパルを検索して選択します
- 「レビューと割り当て」で確定します
ポイント: RBACreの割り当て先はサービスプリンシパル(エンタープライズアプリケーション側)のオブジェクトIDに紐付きます。アプリケーション登録のオブジェクトIDとは異なるので注意してください。
パターン1:パスワードベース認証(クライアントシークレット)
クライアントシークレットを作成する
- 「アプリの登録」で対象のアプリケーションを開きます
- 「証明書とシークレット」→「クライアントシークレット」→「新しいクライアントシークレット」を選択します
- 説明と有効期限(最大24か月)を設定して「追加」します
- 作成直後に表示される値を必ずコピーしてください。この値は作成直後しか表示されません
重要: シークレットの値は作成後に再表示できません。必ず安全な場所に保存してください。
PowerShellでサービスプリンシパルとして認証する
以下の3つの情報を用意します。
$appId:アプリケーション(クライアント)ID$clientSecret:作成したクライアントシークレットの値$tenantId:ディレクトリ(テナント)ID
$appId = "<アプリケーションID>"
$clientSecret = "<クライアントシークレットの値>"
$tenantId = "<テナントID>"
# クライアントシークレットをSecureStringに変換する
$secureSecret = ConvertTo-SecureString $clientSecret -AsPlainText -Force
# PSCredentialオブジェクトを作成する
$credential = New-Object System.Management.Automation.PSCredential($appId, $secureSecret)
# サービスプリンシパルとして認証する
Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId
認証が成功すると、ブラウザや多要素認証の画面が一切表示されずにAzureへのサインインが完了します。
認証後の確認と操作例は以下のとおりです。
# 現在のコンテキストを確認する
Get-AzContext
# アクセストークンを取得する
Get-AzAccessToken
# リソースグループを作成する
New-AzResourceGroup -Name "myResourceGroup" -Location "japaneast"
パスワードベースの問題点
クライアントシークレットを使った認証は手軽ですが、深刻なセキュリティリスクがあります。
上記のスクリプトを見るとわかるように、シークレットの値がソースコード上にプレーンテキストとして存在しています。このスクリプトが第三者の目に触れた場合、サービスプリンシパルが乗っ取られてしまいます。
原則: パスワードベースの認証は本番環境での使用を避けてください。学習や検証目的にとどめ、本番環境では次に紹介する証明書ベースの認証を使用してください。
パターン2:証明書ベース認証(本番環境推奨)
証明書ベースの認証では、Windowsの証明書ストアに秘密鍵を安全に保管できるため、スクリプト上にパスワードを書かずに済みます。
証明書を作成する
PowerShellで自己署名証明書を作成します。
# Windowsの証明書ストア(CurrentUser\My)に自己署名証明書を作成する
New-SelfSignedCertificate `
-CertStoreLocation "cert:\CurrentUser\My" `
-Subject "CN=cert-for-sp"
公開鍵をエクスポートする
証明書管理コンソール(certmgr.msc)を開いて操作します。
- 「個人」→「証明書」に作成した証明書が表示されます
- 証明書をダブルクリックして内容を確認します
- 「すべてのタスク」→「エクスポート」を選択します
- エクスポートウィザードで「秘密キーをエクスポートしない」を選択します
- ファイル形式はデフォルト(DER encoded binary X.509)のままにします
- ファイル名を指定して(例:
cert.cer)エクスポートします
ポイント: Entra IDへアップロードするのは公開鍵のみです。秘密鍵は自分のマシンから外に出しません。これにより「秘密鍵を持っているマシンだけが認証できる」という安全な状態が作れます。
Entra IDに証明書をアップロードする
- 「アプリの登録」で対象のアプリケーションを開きます
- 「証明書とシークレット」→「証明書」→「証明書のアップロード」を選択します
- 先ほどエクスポートした
.cerファイルをアップロードします - アップロード後に表示される**拇印(Thumbprint)**を控えておきます
PowerShellで証明書を使って認証する
# 証明書の拇印を取得する
$thumbprint = (Get-ChildItem -Path "cert:\CurrentUser\My" | Where-Object { $_.Subject -match "cert-for-sp" }).Thumbprint
$appId = "<アプリケーションID>"
$tenantId = "<テナントID>"
# 証明書を使ってサービスプリンシパルとして認証する
Connect-AzAccount `
-ServicePrincipal `
-CertificateThumbprint $thumbprint `
-ApplicationId $appId `
-Tenant $tenantId
認証が成功すれば、シークレット認証と同様にトークン取得やリソース操作が行えます。
# コンテキストの確認
Get-AzContext
# リソースグループの作成
New-AzResourceGroup -Name "myResourceGroup" -Location "japaneast"
まとめ
今回はサービスプリンシパルを使ってAzureの処理を完全自動化する方法を解説しました。
- Entra IDにアプリケーション登録を行うと、裏側でサービスプリンシパルも自動作成されます
- サービスプリンシパルへのRBAC権限付与は、エンタープライズアプリケーション側のオブジェクトIDに対して行われます
- クライアントシークレット(パスワードベース) を使うと手軽に認証できますが、ソースコードへの平文記載はセキュリティリスクがあるため、本番環境での使用は避けてください
- 証明書ベースの認証であれば秘密鍵をWindows証明書ストアに安全に保管でき、本番環境でも使用できます
次回は、シークレットや証明書を複数人・複数マシンで安全に共有するための方法を解説する予定です。