Public/Get-IOExpiringSSOCerts.ps1
|
function Get-IOExpiringSSOCerts { <# .SYNOPSIS Scans enterprise apps for SAML/SSO signing certificates that are expiring. .EXAMPLE Get-IOExpiringSSOCerts -DaysUntilExpiry 60 .EXAMPLE Get-IOExpiringSSOCerts -DaysUntilExpiry 30 -ToCsv "sso-certs.csv" #> [CmdletBinding()] param( [ValidateRange(1, 3650)] [int]$DaysUntilExpiry = 30, [switch]$IncludeExpired, [string]$ToCsv ) $cmdName = $MyInvocation.MyCommand.Name Write-IOLog "Scanning enterprise apps for SSO certificates expiring within $DaysUntilExpiry days..." -Level Info -Component $cmdName $now = [datetime]::UtcNow $cutoff = $now.AddDays($DaysUntilExpiry) $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Get service principals that have SAML SSO configured $sps = Invoke-IOGraphRequest -Uri "v1.0/servicePrincipals?`$select=id,displayName,appId,preferredSingleSignOnMode,keyCredentials,passwordCredentials" foreach ($sp in $sps) { # Only check apps with SAML SSO if ($sp.preferredSingleSignOnMode -ne 'saml' -and -not $sp.keyCredentials) { continue } if ($sp.keyCredentials) { foreach ($cred in $sp.keyCredentials) { if (-not $cred.endDateTime) { continue } $endDate = [datetime]::Parse($cred.endDateTime, [System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::AssumeUniversal) $isExpired = $endDate -lt $now $isExpiring = $endDate -le $cutoff if ($isExpiring -or ($IncludeExpired -and $isExpired)) { $results.Add([PSCustomObject]@{ ApplicationName = $sp.displayName ApplicationId = $sp.appId ObjectId = $sp.id SSOMode = $sp.preferredSingleSignOnMode CredentialType = $cred.type Usage = $cred.usage KeyId = $cred.keyId ExpiryDate = $endDate.ToString('yyyy-MM-dd') DaysRemaining = [math]::Floor(($endDate - $now).TotalDays) Status = if ($isExpired) { 'EXPIRED' } else { 'EXPIRING' } }) } } } } $sorted = $results | Sort-Object DaysRemaining Export-IOResult -Data $sorted -ToCsv $ToCsv -CommandName $cmdName } |