diff --git a/Azure/Azure-App-Expiration.ps1 b/Azure/Azure-App-Expiration.ps1 new file mode 100644 index 0000000..e839f1b --- /dev/null +++ b/Azure/Azure-App-Expiration.ps1 @@ -0,0 +1,254 @@ +<# +.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 = "v0.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 information + $AzureADApps = Get-MgApplication | Sort-Object DisplayName + $AppCertificateDetails = @() #Initiate the array to store the collected information + $AppClientSecretsDetails = @() #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 + } + } + } + } +#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 += @" +

Application Secrets Overview

+ + + + + + + + +"@ + foreach ($AppClientSecretsDetail in $AppClientSecretsDetails) { + $htmlReport += @" + + + + + + + $(switch ($AppClientSecretsDetail.Status) { + 'ERROR' {""} + 'WARNING' {""} + default {""} + } ) + +"@ + } + $htmlReport += "
App DisplayNameSecret NameEnddateDays RemainingStatus
$($AppClientSecretsDetail.AppDisplayName)$($AppClientSecretsDetail.SecretName)$($AppClientSecretsDetail.Enddate)$($AppClientSecretsDetail.DaysRemaining)$($AppClientSecretsDetail.Status)$($AppClientSecretsDetail.Status)$($AppClientSecretsDetail.Status)
" + } + $htmlReport += @" +

This is an automated report. +

+ + +"@ +#endregion + +#region send reports and generate summary report + # Send the report via email + $Status = "OK" + switch ($licenseUsageData | Select-Object -ExpandProperty LicenseStatus) { + { $_ -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)" + } + } + Write-Summary "---------------------------" +#endregion \ No newline at end of file