【Q&Aコーナー】クライアントシークレットの更新時期を把握する

Microsoft Entra IDでアプリを登録する場合、エンタープライズアプリケーションから登録するケースとアプリの登録から登録するケースがあります。

・エンタープライズアプリケーションには証明書 (SAMLの場合)、
・アプリの登録にはクライアントシークレット (シークレットを設定した場合)

という有効期間が設定されるコンテンツが実装されます。

有効期間があるということは期限が切れたらアプリにアクセスできなくなるという問題が起きるわけで、管理者としては有効期間が切れそうな状態になっていないかの監視は必要な作業となります。

ところがMicrosoft Entra IDでは証明書の期限が切れそうになると、メールで通知をしてくれるけど、クライアントシークレットは期限が切れそうになっても何も教えてくれない。

有効期限をめっちゃ長い期間にするという手もありますが、

実運用ではあまり現実的ではないと思いますので、
クライアントシークレットの期限が切れそうになったらメールで通知するような仕組みが必要になると思います。

そこで以下のようなスクリプトを作ってみました。

# メール送信者/受信者
$upn = "aaa@aaa.com"
#有効期間切れまでの残り日数
$thresholdDays = 30
$nowUtc = (Get-Date).ToUniversalTime()

# サインイン
Connect-MgGraph -Scopes "Application.Read.All","Mail.Send"

# アプリの情報を取得
$apps = Get-MgApplication -All -Property 'Id,DisplayName,PasswordCredentials'

# 送信者(委任)を取得
$me = Get-MgUser -UserId $upn
$to = @{ EmailAddress = @{ Address = $upn } }

foreach ($app in $apps) {
    # パスワード資格情報が存在するアプリのみ処理
    if ($app.PasswordCredentials -and $app.PasswordCredentials.Count -gt 0) {

        foreach ($pc in $app.PasswordCredentials) {
            # endDateTime が無いものはスキップ
            if (-not $pc.endDateTime) { continue }

            $end = [DateTime]$pc.endDateTime
            $daysLeft = [math]::Floor(($end.ToUniversalTime() - $nowUtc).TotalDays)

            # 期限がしきい値以内 & まだ未期限切れ
            if ($daysLeft -le $thresholdDays -and $daysLeft -ge 0) {

                # 本文(1シークレットにつき1通送信)
                $bodyText = @"
以下のクライアントシークレットの有効期限が $thresholdDays 日以内です。

- アプリ名: $($app.DisplayName)
  ObjectId: $($app.Id)
  SecretDisplayName: $($pc.displayName)
  KeyId: $($pc.keyId)
  Expires(UTC): $($end.ToString('yyyy-MM-dd HH:mm:ss'))
  DaysLeft: $daysLeft

-- 自動通知
"@

                try {
                    Send-MgUserMail -UserId $me.Id -Message @{
                        Subject = "[Alert] クライアントシークレット期限間近 ($($app.DisplayName))"
                        Body    = @{ ContentType = 'Text'; Content = $bodyText }
                        ToRecipients = @($to)
                    } -SaveToSentItems -ErrorAction Stop

                    Write-Host "Sent: $($app.DisplayName) / KeyId: $($pc.keyId) ($daysLeft days left)"
                }
                catch {
                    Write-Warning "送信失敗: $($app.DisplayName) / KeyId: $($pc.keyId) -> $($_.Exception.Message)"
                }
            }
        }
    }
}

Connect-MgGraph コマンドレットは普通に実行するとサインイン画面が出てきてしまうので、タスクスケジューラなどから登録して自動実行する場合はサインインを自動化する工夫をしてあげる必要があります。その方法は、、って書こうとしたら既に解説してくださっている方がいました。

スクリプトは実行されると、期限が切れそうなクライアントシークレットを見つけ、こんな感じでメールが送られてきます。

参考になれば幸いです。