Skip to content

Instantly share code, notes, and snippets.

@AlexAsplund
Created October 30, 2019 12:24
Show Gist options
  • Save AlexAsplund/8876454d9c25668942a012c158fcef1f to your computer and use it in GitHub Desktop.
Save AlexAsplund/8876454d9c25668942a012c158fcef1f to your computer and use it in GitHub Desktop.
param(
# User = ClientId Pass = Secret
[parameter(Mandatory)]
[PSCredential]$Credential,
[parameter(Mandatory)]
$TenantName
[parameter(Mandatory)]
$GelfServer
)
Import-Module PSGELF
<#
.SYNOPSIS
Gets a graph access token
.DESCRIPTION
Gets a graph access token with client credentials.
You need to create a new app in azure AD and supply it [pscredential]$ClientCredential.
Username = application id
Password = Application key/client secret
.EXAMPLE
PS C:\> Get-MyAADAccessToken -ClientCredential $Credential -TenantName contoso.onmicrosoft.com
Explanation of what the example does
#>
Function Get-MyAADAccessToken {
param(
# application secrets. Username = application id, password = client secret
[parameter(Mandatory)]
[PSCredential]$ClientCredential,
# Name of your tenant. ie contoso.onmicrosoft.com
[parameter(Mandatory)]
[string]$TenantName
)
Add-Type -AssemblyName System.Web
# Decode securestring
$SecureString = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($ClientCredential.password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($SecureString)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($SecureString)
$BodyList = @(
"client_id=$([System.Web.HttpUtility]::UrlEncode($ClientCredential.UserName))"
"scope=https%3A%2F%2Fgraph.microsoft.com%2F.default"
"client_secret=$([System.Web.HttpUtility]::UrlEncode($Password))",
"grant_type=client_credentials"
)
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
Body = ($BodyList -join '&')
Uri = $Url
}
$Request = Invoke-RestMethod @PostSplat
return $Request
}
Function Get-UnixTimeStamp($Date){
(New-TimeSpan -Start (Get-Date "01/01/1970") -End ($Date)).TotalSeconds
}
Function Flatten-Object { # https://powersnippets.com/flatten-object/
[CmdletBinding()]Param ( # Version 02.00.16, by iRon
[Parameter(ValueFromPipeLine = $True)][Object[]]$Objects,
[String]$Separator = ".", [ValidateSet("", 0, 1)]$Base = 1, [Int]$Depth = 5, [Int]$Uncut = 1,
[String[]]$ToString = ([String], [DateTime], [TimeSpan], [Version], [Enum]), [String[]]$Path = @()
)
$PipeLine = $Input | ForEach {$_}; If ($PipeLine) {$Objects = $PipeLine}
If (@(Get-PSCallStack)[1].Command -eq $MyInvocation.MyCommand.Name -or @(Get-PSCallStack)[1].Command -eq "<position>") {
$Object = @($Objects)[0]; $Iterate = New-Object System.Collections.Specialized.OrderedDictionary
If ($ToString | Where {$Object -is $_}) {$Object = $Object.ToString()}
ElseIf ($Depth) {$Depth--
If ($Object.GetEnumerator.OverloadDefinitions -match "[\W]IDictionaryEnumerator[\W]") {
$Iterate = $Object
} ElseIf ($Object.GetEnumerator.OverloadDefinitions -match "[\W]IEnumerator[\W]") {
$Object.GetEnumerator() | ForEach -Begin {$i = $Base} {$Iterate.($i) = $_; $i += 1}
} Else {
$Names = If ($Uncut) {$Uncut--} Else {$Object.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames}
If (!$Names) {$Names = $Object.PSObject.Properties | Where {$_.IsGettable} | Select -Expand Name}
If ($Names) {$Names | ForEach {$Iterate.$_ = $Object.$_}}
}
}
If (@($Iterate.Keys).Count) {
$Iterate.Keys | ForEach {
Flatten-Object @(,$Iterate.$_) $Separator $Base $Depth $Uncut $ToString ($Path + $_)
}
} Else {$Property.(($Path | Where {$_}) -Join $Separator) = $Object}
} ElseIf ($Objects -ne $Null) {
@($Objects) | ForEach -Begin {$Output = @(); $Names = @()} {
New-Variable -Force -Option AllScope -Name Property -Value (New-Object System.Collections.Specialized.OrderedDictionary)
Flatten-Object @(,$_) $Separator $Base $Depth $Uncut $ToString $Path
$Output += New-Object PSObject -Property $Property
$Names += $Output[-1].PSObject.Properties | Select -Expand Name
}
$Output | Select ([String[]]($Names | Select -Unique))
}
}
$AccessToken = (Get-MyAADAccessToken -TenantName $TenantName -ClientCredential $Credential).access_token
$Header = @{
Authorization = 'Bearer '+$AccessToken
}
if(!(Test-Path $PSScriptRoot\LastActivity.txt)){
$FromDate = (get-date -Hour 0 -minute 0 -Second 0 -Millisecond 0 -format "yyyy-MM-dd")
}
else{
$FromDate = Cat $PSScriptRoot\lastactivity.txt -Encoding UTF8
if([string]::IsNullOrEmpty($FromDate)){
$FromDate = (get-date -Hour 0 -minute 0 -Second 0 -Millisecond 0 -format "yyyy-MM-dd")
}
}
$Events = @()
$Request = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/security/alerts?`$filter=eventDateTime ge $FromDate" -Headers $Header
$Events += $Request.value
while($Request.'@odata.nextLink' -ne $null){
$Request = Invoke-RestMethod -Uri $Request.'@odata.nextLink' -Headers $Header
Write-Output $Request.'@odata.nextLink'
$Events += $Request.Value
$More = $Request.'@odata.nextLink' -ne $null
}
$n = 0
$c = ($Events | measure).Count
foreach($Event in $Events){
$NewEvent = [PSCustomObject]@{
Message = $Event.Title + "|" +$Event.description
json = $Event | flatten-object | ConvertTo-Json -Depth 20
Type = "AzureAlerts"
host = 'AzureAlerts'
}
$NewEvent | Send-PSGelfTCPFromObject -GelfServer GelfServer -Port 12201
$n;$n++
}
Write-Output "Sent $(($Events | Measure).Count) events"
$LastEvent = $Events.eventDateTime | ? {![string]::IsNullOrEmpty($_)} | sort | select -last 1
if(![string]::IsNullOrEmpty($LastEvent)){
$LastEvent | Out-File -Encoding utf8 -FilePath $PSScriptRoot\lastactivity.txt
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment