PrivilegedUsersAudit.psm1
function Get-PrivilegedUsers { <# .SYNOPSIS Output's an HTML report with CSV output of Privilaged Users and optionally sends attachment as an email. Function App URI can be used in the place of a password. .DESCRIPTION Output's an HTML audit report with CSV output of Privilaged Users and additional domain health info. .EXAMPLE PS C:\> Get-PrivilegedUsers -Verbose .EXAMPLE PS C:\> Get-PrivilegedUsers -SendMailMessage -UserName "helpdesk@domain.com" -Uri "https://<instance>.azurewebsites.net/api/HttpTrigger1?code=<Personal URL CODE>&clientId=<FunctionHTMLName>" -To "support@domain.com" -Verbose .EXAMPLE PS C:\> Get-PrivilegedUsers -SendMailMessage -UserName "helpdesk@domain.com" -Password "Password" -To "support@domain.com" -Verbose .PARAMETER UserName Specify the account with an active mailbox and MFA disabled. Ensure the account has delegated access for Send On Behalf for any UPN set in the "$From" Parameter .PARAMETER Uri Function App URL for specific customer or department needing access to the key. .PARAMETER Password Use this parameter to active the parameterset associated with using a clear-text password instead of a function URI. .PARAMETER To Recipient of the attachment outputs. .PARAMETER From Defaults to the same account as $UserName unless the parameter is set. The email will appear as it was sent from the UPN listed here. Ensure the Account stated in the $UserName has delegated access to send on behalf of the account you add to the $From parameter. .PARAMETER AttachementFolderPath Default path is C:\temp\PrivilegedUsersAuditLogs. This is the folder where attachments are going to be saved. .PARAMETER SMTPServer Defaults to Office 365 SMTP relay. Enter optional relay here. .PARAMETER Port SMTP Port to Relay .PARAMETER Clean Remove installed modules during run. .PARAMETER SendMailMessage Adds parameters for sending Audit Report as an Email. .NOTES Can take password as input into secure string instead of URI. Adding the password parameter right after username when calling the function with SendMailMessage will trigger the correct parameter set. .INPUTS System.String System.Management.Automation.SwitchParameter System.Security.SecureString System.Int32 .OUTPUTS System.Object .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = 'Local')] param ( [Parameter( Position = '0', ParameterSetName = 'URL Key Vault')] [Parameter( Position = '0', ParameterSetName = 'Password')] [Parameter( Position = '0', ParameterSetName = 'Local', HelpMessage = 'Enter output folder path', ValueFromPipelineByPropertyName = $true )] [string]$AttachementFolderPath = "C:\temp\PrivilegedUsersAuditLogs", [Parameter(Mandatory = $true, Position = '1', ParameterSetName = 'URL Key Vault')] [Parameter(Mandatory = $true, Position = '1', ParameterSetName = 'Password')] [Parameter( Position = '1', ParameterSetName = 'Local', HelpMessage = "Activate Mail Parameters", ValueFromPipelineByPropertyName = $true )] [switch]$SendMailMessage, [Parameter( Position = '2', Mandatory = $true, ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true )] [securestring]$Password, [Parameter( Position = '2', Mandatory = $true, ParameterSetName = 'URL Key Vault', ValueFromPipelineByPropertyName = $true )] [string]$Uri, [Parameter(Mandatory = $true, Position = '3', ParameterSetName = 'URL Key Vault')] [Parameter( Position = '3', Mandatory = $true, ParameterSetName = 'Password', HelpMessage = "UPN as in user@contoso.com", ValueFromPipelineByPropertyName = $true )] [string]$UserName, [Parameter(ParameterSetName = 'URL Key Vault')] [Parameter( ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true )] [string]$SMTPServer = "smtp.office365.com", [Parameter(ParameterSetName = 'URL Key Vault')] [Parameter( ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true )] [int]$Port = "587", [Parameter(Mandatory = $true, ParameterSetName = 'URL Key Vault')] [Parameter( Mandatory = $true, ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true )] [string]$To, [Parameter(ParameterSetName = 'URL Key Vault')] [Parameter( HelpMessage = "Defaults to Username", ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true )] [string]$From = $UserName, [Parameter( HelpMessage = "Cleans up modules", ValueFromPipelineByPropertyName = $true )] [switch]$Clean ) Begin { # Check for admin and throw exception if not running elevated. $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) if (!($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))) { throw "Not Running as admin! Please rerun as administrator!" } # Set TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Create Log Path $DirPath = $AttachementFolderPath $DirPathCheck = Test-Path -Path $DirPath If (!($DirPathCheck)) { Try { #If not present then create the dir New-Item -ItemType Directory $DirPath -Force } Catch { throw "Directory: $DirPath was not created." } } # Begin Logging Start-Transcript -OutputDirectory $DirPath -IncludeInvocationHeader -NoClobber if ($SendMailMessage) { # Install / Import required modules. $module = Get-Module -Name Send-MailKitMessage -ListAvailable if (-not $module) { Install-Module -Name Send-MailKitMessage -AllowPrerelease -Scope AllUsers -Force } try { Import-Module "Send-MailKitMessage" -Global } catch { throw "The Module Was not installed. Use `"Save-Module -Name Send-MailKitMessage -AllowPrerelease -Path C:\temp`" on another Windows Machine." } } } Process { # Create CSV Path Prefix $csvPath = "$attachementfolderpath\$($env:USERDNSDOMAIN)_AD_PrivilegedUsersExport" $DirPath2 = "$csvPath\$((Get-Date).ToString('yyyy-MM-dd.hh'))" $DirPathCheck = Test-Path -Path $DirPath2 If (!($DirPathCheck)) { Try { #If not present then create the dir New-Item -ItemType Directory $DirPath2 -Force } Catch { throw "Directory: $DirPath2 was not created." } } # End If # Set PWD to $DirPath Set-Location $DirPath2 # Build Zip file path $zip = "$($DirPath2)\$((Get-Date).ToString('yyyy-MM-dd.hh.mm.ss')).PrivilegedUsersAudit.zip" # Get ADAssetReport for PrivilegedUsers Get-ADAssetReport -ExportPrivilegedUsers -Verbose Compress-Archive -Path "$($DirPath2)\*" -DestinationPath $zip } End { if ($SendMailMessage) { if ($Password) { <# Send Attachement using O365 email account and password. Must exclude from conditional access legacy authentication policies. #> Send-AuditEmail -smtpServer $SMTPServer -port $Port -username $Username ` -pass $Password -from $from -to $to -attachmentfilePath "$zip" -ssl } # End if else { <# Send Attachement using O365 email account and Keyvault retrived password. Must exclude email account from conditional access legacy authentication policies. #> Send-AuditEmail -smtpServer $SMTPServer -port $Port -username $Username ` -url $uri -from $from -to $to -attachmentfilePath "$zip" -ssl } # End Else } if ($Clean) { try { # Remove Modules Remove-Module -Name "Send-MailKitMessage" -Force -Confirm:$false ` -ErrorAction SilentlyContinue -ErrorVariable RemoveModErr } catch { Write-Output $RemoveModErr -Verbose } try { # Uninstall Modules Uninstall-Module -Name "Send-MailKitMessage" -AllowPrerelease -Force -Confirm:$false ` -ErrorAction SilentlyContinue -ErrorVariable UninstallModErr } catch { Write-Output $UninstallModErr -Verbose } } # End Logging Stop-Transcript } } function Send-AuditEmail { param ( [string]$smtpServer, [int]$port, [string]$username, [switch]$ssl, [string]$url, [string]$from, [string]$to, [string]$subject = "Active User Audit for $($env:USERDNSDOMAIN)", [string]$attachmentfilePath, [string]$body = "Audit done on $(Get-Date). Attachment file: $attachmentfilePath", [securestring]$pass ) Import-Module Send-MailKitMessage # Recipient $RecipientList = [MimeKit.InternetAddressList]::new() $RecipientList.Add([MimeKit.InternetAddress]$to) # Attachment $AttachmentList = [System.Collections.Generic.List[string]]::new() $AttachmentList.Add("$attachmentfilePath") # From $from = [MimeKit.MailboxAddress]$from # Mail Account variable $User = $username if ($pass) { # Set Credential to $Password parameter input. $Credential = $pass } else { # Retrieve credentials from function app url into a SecureString. try { $Credential = ` [System.Management.Automation.PSCredential]::new($User, (ConvertTo-SecureString -String "$(Invoke-RestMethod -Uri $url)" -AsPlainText -Force)) } catch { throw "Unable to retrieve password from url" } } # Create Parameter hashtable $Parameters = @{ "UseSecureConnectionIfAvailable" = $ssl "Credential" = $Credential "SMTPServer" = $SMTPServer "Port" = $Port "From" = $From "RecipientList" = $RecipientList "Subject" = $subject "TextBody" = $body "AttachmentList" = $AttachmentList } Send-MailKitMessage @Parameters } |