diff --git a/Azure/Azure-App-Expiration.ps1 b/Azure/Azure-App-Expiration.ps1
new file mode 100644
index 0000000..117b112
--- /dev/null
+++ b/Azure/Azure-App-Expiration.ps1
@@ -0,0 +1,313 @@
+<#
+.SYNOPSIS
+ This script generates an report with all the App Secrets of the Azure applications
+
+.DESCRIPTION
+ This PowerShell script connects to the Microsoft Graph API, retreives all the Applications that are configured in the Azure Tenant and make use of an secret
+ with a expiration date. Finaly the script will create a report based on the information collected by The GraphAPI.
+
+.PARAMETER None
+ This script does not require any parameters.
+
+.EXAMPLE
+ .\Azure-App-Expiration.ps1
+
+.NOTES
+ This script is intended for use in a test or production environment. Make sure to test the script in a non-production environment before running it in production.
+ Author: D.de Kooker - info@dcomputers.nl
+
+ DISCLAIMER: Use scripts at your own risk, if there is anything I can help you with I will try but I do not take responsibility for the way that anyone else uses my scripts.
+ Sharing is caring. Share your knowledge with the world so that everybody can learn from it.
+
+.LINK
+ The latest version can Always be found on my GIT page on the link below:
+ https://git.dcomputers.nl/Dcomputers/PowershellScripts
+#>
+
+#region Global script settings and variables
+ #General
+ $Version = "v1.1"
+ $logfilelocation = "$($MyInvocation.MyCommand.Path | Split-Path -Parent)\Logs"
+ $logfilename = "$(Get-Date -Format yyyyMMddHHmmss)-Azure-App-Expiration-Report.log"
+ $summaryfilename = "$(Get-Date -Format yyyyMMddHHmmss)-Azure-App-Expiration-Summary.txt"
+ $WarningDays = "31" #Specify the amount of days for a warning status
+
+ #Azure Enterprise app configuration
+ $STR_TenantID = ""
+ $STR_AppID = ""
+ $STR_ClientSecret = ""
+
+ #Email report settings
+ $STR_SMTPServer = ""
+ $STR_SMTPServerPort = ""
+ $STR_SMTPUsername = ""
+ $STR_SMTPPassword = ""
+ $STR_EmailSubject= "Azure App expiration report - $(Get-Date -Format "dd-MM-yyyy")"
+ $STR_SMTPFromaddress = "Servicedesk ICT "
+ $STR_Receivers = "servicedesk@contoso.com,systemengineer1@contoso.com" #List of commaseperated emailaddresses
+#endregion
+
+#region functions
+ function SendMailv2 ($To,$Subject,$Body){
+ $SMTPClient = New-Object Net.Mail.SmtpClient($STR_SMTPServer, $STR_SMTPServerPort)
+ # $SMTPClient.EnableSsl = $true
+ $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($STR_SMTPUsername, $STR_SMTPPassword);
+ $SMTPMessage = New-Object System.Net.Mail.MailMessage($STR_SMTPFromaddress,$To,$Subject,$Body)
+ $SMTPMessage.IsBodyHTML = $true
+ $SMTPClient.Send($SMTPMessage)
+ }
+ function Initiate-Log {
+ # Get current user and session information
+ $username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
+ $computerName = $env:COMPUTERNAME
+ $sessionID = $pid
+ $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
+
+ # Write log header
+ $logHeader = "[$date] Log initiated by $username on $computerName (Session ID: $sessionID)"
+ Add-Content -Path $logfilelocation\$logfilename -Value "**********************"
+ Add-Content -Path $logfilelocation\$logfilename -Value "LogFile initiation"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Start time: $date"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Username: $username"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Machine: $computerName"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Process ID: $sessionID"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Script Version: $Version"
+ Add-Content -Path $logfilelocation\$logfilename -Value "Script Source: https://git.dcomputers.nl/Dcomputers/PowershellScripts"
+ Add-Content -Path $logfilelocation\$logfilename -Value "**********************"
+ }
+
+ function Write-Log {
+ [CmdletBinding()]
+ Param (
+ [Parameter(Mandatory=$true)]
+ [string]$Message,
+ [Parameter(Mandatory=$false)]
+ [ValidateSet("INFO", "WARNING", "ERROR")]
+ [string]$Level = "INFO"
+ )
+ $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
+ $logmessage = "[$timestamp] [$Level] $Message"
+ Add-Content -Path $logfilelocation\$logfilename -Value $logmessage
+ }
+
+ function Write-Summary {
+ [CmdletBinding()]
+ Param (
+ [Parameter(Mandatory=$true)]
+ [string]$Message
+ )
+ Add-Content -Path $logfilelocation\$summaryfilename -Value $Message
+ }
+#endregion
+
+#region prerequisites check
+ #Create log directory if not present and initiate logfile
+ if (!(test-path $logfilelocation)) {mkdir $logfilelocation}
+ Initiate-Log
+
+ #Check if the required Powershell Modules are available
+ $modules = @("Microsoft.Graph")
+ foreach ($module in $modules) {
+ if (!(Get-Module -Name $module -ListAvailable)) {
+ Write-Host "The $module module is not installed. Please install it and try again."
+ Write-Log -Message "The $module module is not installed. Please install it and try again." -Level ERROR
+ exit 1
+ }
+ }
+
+ #Setup MSGraph connection
+ $ClientSecretPass = ConvertTo-SecureString -String $STR_ClientSecret -AsPlainText -Force
+ $ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $STR_AppID, $ClientSecretPass
+ Connect-MgGraph -TenantId $STR_TenantID -ClientSecretCredential $ClientSecretCredential -NoWelcome
+ Write-Log -Message "Connected to MsGraph API" -Level INFO
+#endregion
+
+#region execute script
+ #Collect all app Registration information
+ $AzureADApps = Get-MgApplication -all | Sort-Object DisplayName
+ $AppClientSecretsDetails = @() #Initiate the array to store the collected information
+ $AppCertificateDetails = @() #Initiate the array to store the collected information
+
+ foreach ($App in $AzureADApps) {
+ #Script should be extended to also include Certificates, preparations are already made.
+ #Collect Client Secret details if available
+ if ($null -ne $App.PasswordCredentials) {
+ foreach ($PasswordCredential in $App.PasswordCredentials) {
+ #Calculate remaining days
+ $RemainingDays = New-TimeSpan -Start $(Get-Date) -End $PasswordCredential.EndDateTime
+ $DaysRemaining = $RemainingDays.Days
+ switch ($DaysRemaining) {
+ {$_ -le '0'} {$CalculatedStatus = "ERROR"}
+ {$_ -le $WarningDays} {$CalculatedStatus = "WARNING"}
+ Default {$CalculatedStatus = "OK"}
+ }
+
+ $AppClientSecretsDetails += [PSCustomObject]@{
+ AppDisplayName = $App.DisplayName
+ SecretName = $PasswordCredential.Displayname
+ Enddate = $PasswordCredential.EndDateTime
+ DaysRemaining = $DaysRemaining
+ Status = $CalculatedStatus
+ }
+ }
+ }
+ #Collect Client Secret details if available
+ if ($null -ne $App.KeyCredentials) {
+ foreach ($KeyCredential in $App.KeyCredentials) {
+ #Calculate remaining days
+ $RemainingDays = New-TimeSpan -Start $(Get-Date) -End $KeyCredential.EndDateTime
+ $DaysRemaining = $RemainingDays.Days
+ switch ($DaysRemaining) {
+ {$_ -le '0'} {$CalculatedStatus = "ERROR"}
+ {$_ -le $WarningDays} {$CalculatedStatus = "WARNING"}
+ Default {$CalculatedStatus = "OK"}
+ }
+
+ $AppCertificateDetails += [PSCustomObject]@{
+ AppDisplayName = $App.DisplayName
+ CertificateName = $KeyCredential.Displayname
+ Enddate = $KeyCredential.EndDateTime
+ DaysRemaining = $DaysRemaining
+ Status = $CalculatedStatus
+ }
+ }
+ }
+ }
+#endregion
+
+# Create an HTML report
+$htmlReport = @"
+
+
+
+
+
+
+ Azure App expiration report - $(Get-Date -Format "dd-MM-yyyy - HH:mm")
+ Script version: $Version
+"@
+ if ("" -ne $AppClientSecretsDetails) { $htmlReport += @"
+ App Registration Secrets Overview
+
+
+ | App DisplayName |
+ Secret Name |
+ Enddate |
+ Days Remaining |
+ Status |
+
+"@
+ foreach ($AppClientSecretsDetail in $AppClientSecretsDetails) {
+ $htmlReport += @"
+
+ | $($AppClientSecretsDetail.AppDisplayName) |
+ $($AppClientSecretsDetail.SecretName) |
+ $($AppClientSecretsDetail.Enddate) |
+ $($AppClientSecretsDetail.DaysRemaining) |
+ $(switch ($AppClientSecretsDetail.Status) {
+ 'ERROR' {"$($AppClientSecretsDetail.Status) | "}
+ 'WARNING' {"$($AppClientSecretsDetail.Status) | "}
+ default {"$($AppClientSecretsDetail.Status) | "}
+ } )
+
+"@
+ }
+ $htmlReport += "
"
+ }
+ if ("" -ne $AppCertificateDetails) { $htmlReport += @"
+ App Registration Certificates Overview
+
+
+ | App DisplayName |
+ Certificate Name |
+ Enddate |
+ Days Remaining |
+ Status |
+
+"@
+ foreach ($AppCertificateDetail in $AppCertificateDetails) {
+ $htmlReport += @"
+
+ | $($AppCertificateDetail.AppDisplayName) |
+ $($AppCertificateDetail.CertificateName) |
+ $($AppCertificateDetail.Enddate) |
+ $($AppCertificateDetail.DaysRemaining) |
+ $(switch ($AppCertificateDetail.Status) {
+ 'ERROR' {"$($AppCertificateDetail.Status) | "}
+ 'WARNING' {"$($AppCertificateDetail.Status) | "}
+ default {"$($AppCertificateDetail.Status) | "}
+ } )
+
+"@
+ }
+ $htmlReport += "
"
+ }
+ $htmlReport += @"
+ This is an automated report.
+
+
+
+"@
+#endregion
+
+#region send reports and generate summary report
+ # Send the report via email
+ $Status = "OK"
+ switch ($AppClientSecretsDetails.status + $AppCertificateDetails.status) {
+ { $_ -contains "ERROR" } { $Status = "ERROR"; break }
+ { $_ -contains "WARNING" } { $Status = "WARNING"; break }
+ }
+ if ($Status -ne "OK") {
+ $subject = "$($Status): $STR_EmailSubject"
+ }
+ else {
+ $subject = "$STR_EmailSubject"
+ }
+ $body = $htmlReport
+ SendMailv2 -To $STR_Receivers -Subject $subject -Body $body
+
+ # write summary
+ Write-Summary "Azure App Secrets expiration report Summary:"
+ Write-Summary "---------------------------"
+ Write-Summary "Report date: $(Get-Date -Format "dd-MM-yyy HH:mm:ss")"
+ if ("" -ne $AppClientSecretsDetails) {
+ Write-Summary "App Client Secrets"
+ foreach ($AppClientSecretsDetail in $AppClientSecretsDetails) {
+ Write-Summary "******************"
+ Write-Summary "App DisplayName: $($AppClientSecretsDetail.AppDisplayName)"
+ Write-Summary "Secret Name: $($AppClientSecretsDetail.SecretName)"
+ Write-Summary "Enddate: $($AppClientSecretsDetail.Enddate)"
+ Write-Summary "Days Remaining: $($AppClientSecretsDetail.DaysRemaining)"
+ Write-Summary "Status: $($AppClientSecretsDetail.Status)"
+ }
+ }
+ if ("" -ne $AppCertificateDetails) {
+ Write-Summary "App Client Secrets"
+ foreach ($AppCertificateDetail in $AppCertificateDetails) {
+ Write-Summary "******************"
+ Write-Summary "App DisplayName: $($AppCertificateDetail.AppDisplayName)"
+ Write-Summary "Certificate Name: $($AppCertificateDetail.CertificateName)"
+ Write-Summary "Enddate: $($AppCertificateDetail.Enddate)"
+ Write-Summary "Days Remaining: $($AppCertificateDetail.DaysRemaining)"
+ Write-Summary "Status: $($AppCertificateDetail.Status)"
+ }
+ }
+ Write-Summary "---------------------------"
+#endregion
\ No newline at end of file