Oct 23 2020 12:36 AM
Hi,
I am trying to get list of SPNs that are going to expire soon. Using Graph API I am executing below powershell script.
I am getting output appid and name always but StartDate and EndDate are not displaying for few of SPN.
Can you please help how to get it ?
Below is Power shell script I am using:
$TenantId = "*************"
$ClientId = "*************"
$ClientSecret = "*************"
$Body = @{
'tenant' = $TenantId
'client_id' = $ClientId
'scope' = 'https://graph.microsoft.com/.default'
'client_secret' = $ClientSecret
'grant_type' = 'client_credentials'
}
$Params = @{
'Uri' = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
'Method' = 'Post'
'Body' = $Body
'ContentType' = 'application/x-www-form-urlencoded'
}
$AuthResponse = Invoke-RestMethod @Params
$Headers = @{'Authorization' = "Bearer $($AuthResponse.access_token)"}
$method = "GET"
$uri2 = "https://graph.microsoft.com/v1.0/applications/{Id}"
$query2 = Invoke-WebRequest -Method $method -Uri $uri2 -ContentType "application/json" -Headers $Headers -ErrorAction Stop
$query2.content | ConvertFrom-Json | select appId,displayName,@{l="SecretExpiryDate";e={$pwdcreds2.passwordCredentials.endDateTime}}
$pwdcreds2.passwordCredentials
I have another Powershell script it is giving startdate and enddate for same SPN but the problem is my Org is not allowed to fetch APP details from Azure AD due to security guidelines.
$ServicePrincipalIds = Get-AzADServicePrincipal | Where {$_.DisplayName -like '*'}
foreach($ServicePrincipalId in $ServicePrincipalIds)
{
$ServicePrincipalInfo = Get-AzADSpCredential -ObjectId $ServicePrincipalId.Id
$ServicePrincipalInfo
}
Thanks,
Brahma
Oct 23 2020 08:13 PM
Solution@Brahmaiah, you can use Azure CLI for exact same purpose. Do the following:
az ad sp list \
--all \
--query "[?passwordCredentials[0].endDate<='$(date -d "+60 days" +%Y-%m-%d)'||keyCredentials[0].endDate<='$(date -d "+60 days" +%Y-%m-%d)'].{\"App ID Display Name\":appDisplayName,\"SP appId\":appId,\"Password Expiry Date\":passwordCredentials[0].endDate, \"Key Expiry Date\":keyCredentials[0].endDate}" \
-o table
Screenshots:
Edit
Execute
Oct 26 2020 08:01 AM
@Command0r thank you so much for your reply.
Can you please suggest why I am not able to get result using Graph API, this is happening only when SPN has too many start and end date. I need run this script in automation account by scheduling without any manual intervention.
Another Power shell script giving result as bellow.
Thanks,
Brahma
Oct 26 2020 02:38 PM - edited Oct 26 2020 02:44 PM
@Brahmaiah, I think you're missing a 'foreach' to go through the collection of the expiring SPs (had no chance to look at it more closely). Anyway, please take a look at the script below that generates a decent report for the same purpose.
$tenantID = '<your TenantID>'
$clientID = '<your ClientID>'
$clientSecret = (ConvertTo-SecureString '<your Client Secret>' -AsPlainText -Force)
$accessToken = Get-MsalToken -clientID $clientID -clientSecret $clientSecret -tenantID $tenantID | Select-Object -Property AccessToken
# MS Graph Apps URI
$aadAppsURI = 'https://graph.microsoft.com/v1.0/applications'
# Get Expiring Creds in x Days
$expiryCheck = 60
$now = (Get-Date).ToUniversalTime()
$expiryLimit = $now.AddDays($expiryCheck)
# MS Graph Directory Audit URI
$signInsURI = 'https://graph.microsoft.com/v1.0/auditLogs/directoryAudits'
# Report Template
$aadAppReportTemplate = [pscustomobject][ordered]@{
displayName = $null
createdDateTime = $null
signInAudience = $null
}
# Get Apps
$aadApplications = @()
$aadApps = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } `
-Uri $aadAppsURI `
-Method Get
$aadApps.value.Count
if ($aadApps.value) {
$aadApplications += $aadApps.value
# More Apps?
if ($aadApps.'@odata.nextLink') {
$nextPageURI = $aadApps.'@odata.nextLink'
do {
$aadApps = $null
$aadApps = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } `
-Uri $nextPageURI `
-Method Get
if ($aadApps.value) {
$aadApplications += $aadApps.value
$aadApplications.value.Count
}
if ($aadApps.'@odata.nextLink') {
$nextPageURI = $aadApps.'@odata.nextLink'
}
else {
$nextPageURI = $null
}
} until (!$nextPageURI)
}
}
$aadApplications = $aadApplications | Sort-Object -Property createdDateTime -Descending
$aadAppsReport = @()
$expiringCredsApps = @()
foreach ($app in $aadApplications) {
$blnExpiringCreds = $false
# Report Output
$reportData = $aadAppReportTemplate.PsObject.Copy()
$reportData.displayName = $app.displayName
$reportData.createdDateTime = $app.createdDateTime
$reportData.signInAudience = $app.signInAudience
# Key Expiry
if ($app.keyCredentials) {
$keys = @()
foreach ($cred in $app.keyCredentials) {
[datetime]$keyExpiry = $cred.endDateTime
if ($keyExpiry -lt $expiryLimit) {
Write-Warning "$($app.displayName): Key expired/expiring on $($keyExpiry)"
$blnExpiringCreds = $true
}
$keys += $app.keyCredentials | Select-Object -Property @{Name = 'displayName'; Expression = { $cred.displayName } }, @{Name = 'keyId'; Expression = { $cred.keyId } }, @{Name = 'startDateTime'; Expression = { $cred.startDateTime } }, @{Name = 'endDateTime'; Expression = { $cred.endDateTime } }
}
$reportData | Add-Member -Type NoteProperty -Name "keyCredentials" -Value @($keys)
}
# Password Expiry
if ($app.passwordCredentials) {
$passwords = @()
foreach ($cred in $app.passwordCredentials) {
[datetime]$keyExpiry = $cred.endDateTime
if ($keyExpiry -lt $expiryLimit) {
Write-Warning "$($app.displayName): Password expired/expiring on $($keyExpiry)"
$blnExpiringCreds = $true
}
$passwords += $app.passwordCredentials | Select-Object -Property @{Name = 'displayName'; Expression = { $cred.displayName } }, @{Name = 'keyId'; Expression = { $cred.keyId } }, @{Name = 'startDateTime'; Expression = { $cred.startDateTime } }, @{Name = 'endDateTime'; Expression = { $cred.endDateTime } }
}
$reportData | Add-Member -Type NoteProperty -Name "passwordCredentials" -Value @($passwords)
}
# SignIns
$appSignIns = $null
$appSignIns = Invoke-RestMethod -Headers @{Authorization = "Bearer $($accessToken.AccessToken)" } `
-Uri "$($signInsURI)?&`$filter=targetResources/any(t: t/id eq `'$($app.id)`')" `
-Method Get
if ($appSignIns.value) {
"$($app.displayName): $($appSignIns.value.Count) recent signIns"
$reportData | Add-Member -Type NoteProperty -Name "recentSignIns" -Value $appSignIns.value.Count
}
else {
"$($app.displayName): $($appSignIns.value.Count) recent signIns"
$reportData | Add-Member -Type NoteProperty -Name "recentSignIns" -Value '0'
}
$aadAppsReport += $reportData
if ($blnExpiringCreds) {
$expiringCredsApps += $reportData
}
}
$expiringCredsApps.count
$expiringCredsApps | Format-Table
# Report
$aadAppsReport | Format-Table -AutoSize
Update the information in the first three lines (i.e., TenantID, ClientID, ClientSecret) with the values from your app registration. Make sure that the app you registered has the following permissions (from Microsoft Graph):
Also, The MSAL.PS module is used for Microsoft Graph Authentication. It can be installed with the following command:
Install-Module -Name MSAL.PS
The first part of the report includes the apps whose credentials will be expiring within the next 60 days (on the number you specified in the ninth line of the script). The second part includes the recent sign-ins info for the SPs that are already exipired or expiring soon. The third part is all about all the registered apps and the audit log of the recent sign-ins (usability stats).
This is something you can schedule and even expand it further to enable notifications using automation.
Oct 23 2020 08:13 PM
Solution@Brahmaiah, you can use Azure CLI for exact same purpose. Do the following:
az ad sp list \
--all \
--query "[?passwordCredentials[0].endDate<='$(date -d "+60 days" +%Y-%m-%d)'||keyCredentials[0].endDate<='$(date -d "+60 days" +%Y-%m-%d)'].{\"App ID Display Name\":appDisplayName,\"SP appId\":appId,\"Password Expiry Date\":passwordCredentials[0].endDate, \"Key Expiry Date\":keyCredentials[0].endDate}" \
-o table
Screenshots:
Edit
Execute