サービスプリンシパルで完全自動化 ─ パスワードと証明書、2つの認証パターン

この記事の内容

  • サービスプリンシパルを使ってユーザーの介在なしにAzureの処理を完全自動化する方法を解説します
  • Microsoft Entra ID(旧Azure AD)でアプリケーション登録とサービスプリンシパル作成の関係を理解します
  • パスワードベース(クライアントシークレット)の認証手順をPowerShellで実践します
  • 証明書ベースの認証手順と、なぜ本番環境では証明書を使うべきかを説明します
  • Connect-AzAccount でサービスプリンシパルとして認証する具体的なコマンドを紹介します

はじめに

このシリーズはAzureの処理を自動化したい方を対象にしています。「対話的な認証を省いてスクリプトを完全自動化したい」「でもパスワードをスクリプトに直書きするのは怖い」という方にぴったりの内容です。

今回は第3回として、ユーザーが一切介在しない完全自動化を実現するサービスプリンシパル認証を取り上げます。


サービスプリンシパルとは

サービスプリンシパルとは、ユーザーではなくアプリケーションやスクリプトが使うためのIDです。サービスプリンシパルはMicrosoft Entra IDに対して資格情報を提出してトークンを取得し、そのトークンを使ってAzureのAPIを叩きます。

認証の流れは次のとおりです。

  1. サービスプリンシパルがEntra IDへ資格情報を提出
  2. 認証が通ればトークンを受け取る
  3. トークンを使ってAzure APIを呼び出す

今回はこの「資格情報」として、パスワードベース(クライアントシークレット)証明書ベース の2パターンを紹介します。


アプリケーション登録とサービスプリンシパルの関係

Entra IDでサービスプリンシパルを使うには、まずアプリケーション登録を行います。ここで少し混乱しやすいポイントがあります。

アプリケーション登録(「アプリの登録」)を作成すると、裏側でエンタープライズアプリケーション(=サービスプリンシパル)も自動的に作成されます

画面意味
アプリの登録アプリケーションの定義(クラスに相当)
エンタープライズアプリケーションサービスプリンシパルのインスタンス(オブジェクトに相当)

プログラミングになじみのある方は「クラスとインスタンス」の関係で捉えると理解しやすいです。両者は同じアプリケーションIDを共有していますが、オブジェクトIDはそれぞれ異なります。


事前準備:アプリケーション登録とRBAC権限の付与

アプリケーションを登録する

  1. Azureポータルで「Microsoft Entra ID」を開きます
  2. 「アプリの登録」→「新規登録」を選択します
  3. 名前を入力します(例:service-sp
  4. 「サポートされているアカウントの種類」はWebアプリを作らない場合は変更不要です
  5. リダイレクトURIも今回は不要なので空のまま「登録」します

登録後に表示されるアプリケーション(クライアント)IDディレクトリ(テナント)ID は後で使用しますので控えておいてください。

サービスプリンシパルにRBAC権限を付与する

サービスプリンシパルがリソースグループを作成できるよう、Azureサブスクリプションで権限を付与します。

  1. Azureポータルで「サブスクリプション」を開きます
  2. 対象のサブスクリプションを選択し「アクセス制御(IAM)」を開きます
  3. 「追加」→「ロールの割り当ての追加」を選択します
  4. ロールとして「共同作成者」を選択します
  5. 「メンバーの選択」でアクセスの割り当て先を「ユーザー、グループ、またはサービスプリンシパル」にします
  6. 作成したサービスプリンシパルを検索して選択します
  7. 「レビューと割り当て」で確定します

ポイント: RBACreの割り当て先はサービスプリンシパル(エンタープライズアプリケーション側)のオブジェクトIDに紐付きます。アプリケーション登録のオブジェクトIDとは異なるので注意してください。


パターン1:パスワードベース認証(クライアントシークレット)

クライアントシークレットを作成する

  1. 「アプリの登録」で対象のアプリケーションを開きます
  2. 「証明書とシークレット」→「クライアントシークレット」→「新しいクライアントシークレット」を選択します
  3. 説明と有効期限(最大24か月)を設定して「追加」します
  4. 作成直後に表示されるを必ずコピーしてください。この値は作成直後しか表示されません

重要: シークレットの値は作成後に再表示できません。必ず安全な場所に保存してください。

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)を開いて操作します。

  1. 「個人」→「証明書」に作成した証明書が表示されます
  2. 証明書をダブルクリックして内容を確認します
  3. 「すべてのタスク」→「エクスポート」を選択します
  4. エクスポートウィザードで「秘密キーをエクスポートしない」を選択します
  5. ファイル形式はデフォルト(DER encoded binary X.509)のままにします
  6. ファイル名を指定して(例:cert.cer)エクスポートします

ポイント: Entra IDへアップロードするのは公開鍵のみです。秘密鍵は自分のマシンから外に出しません。これにより「秘密鍵を持っているマシンだけが認証できる」という安全な状態が作れます。

Entra IDに証明書をアップロードする

  1. 「アプリの登録」で対象のアプリケーションを開きます
  2. 「証明書とシークレット」→「証明書」→「証明書のアップロード」を選択します
  3. 先ほどエクスポートした .cer ファイルをアップロードします
  4. アップロード後に表示される**拇印(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証明書ストアに安全に保管でき、本番環境でも使用できます

次回は、シークレットや証明書を複数人・複数マシンで安全に共有するための方法を解説する予定です。