Forum Discussion
ServicePrincipal StartDate and EndDate not displaying Using Graph API In Power Shell
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
Brahmaiah, you can use Azure CLI for exact same purpose. Do the following:
- Sign-in to your account in azure
- Open up a Cloud shell
- Once Azure Cloud Shell is initialized in the account, click on curly braces in the panel to open editor (see screenshots attached below)
- Insert the following command that will extract expiring SPs in the next 60 days (adjust the timeframe if needed):
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
- Save this script with whatever filename you want ("sp-list" in my case)
- Execute with "bash sp-list"
- Enjoy the list
Screenshots:
Edit
Execute
- Command0rIron Contributor
Brahmaiah, you can use Azure CLI for exact same purpose. Do the following:
- Sign-in to your account in azure
- Open up a Cloud shell
- Once Azure Cloud Shell is initialized in the account, click on curly braces in the panel to open editor (see screenshots attached below)
- Insert the following command that will extract expiring SPs in the next 60 days (adjust the timeframe if needed):
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
- Save this script with whatever filename you want ("sp-list" in my case)
- Execute with "bash sp-list"
- Enjoy the list
Screenshots:
Edit
Execute
- BrahmaiahBrass Contributor
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
- Command0rIron Contributor
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):
- Application.Read.All
- AuditLog.Read.All
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.