Skip to content

Instantly share code, notes, and snippets.

@AlexanderHolmeset
Created May 20, 2025 10:53
Show Gist options
  • Select an option

  • Save AlexanderHolmeset/fe9022f9188fa3ee3e0b6bb5229521c1 to your computer and use it in GitHub Desktop.

Select an option

Save AlexanderHolmeset/fe9022f9188fa3ee3e0b6bb5229521c1 to your computer and use it in GitHub Desktop.
param
(
[Parameter(Mandatory=$false)]
[object] $WebhookData
)
$threshold = 5
# Jira authentication
$Text = "[email protected]:$(Get-AutomationVariable -Name 'JIRA')"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
$EncodedText = [convert]::ToBase64String($bytes)
$headersJira = @{
"Content-Type" = "application/json"
"authorization" = "Basic $EncodedText"
}
# Microsoft Defender authentication
$clientID = "xxxxxx
$clientSecret = Get-AutomationVariable -Name 'Machines - VCenterDefender'
$tenantID = "xxxxxx"
$resource = "https://api.securitycenter.microsoft.com"
$body = @{
grant_type = "client_credentials"
scope = "$resource/.default"
client_id = $clientId
client_secret = $clientSecret
}
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Body $body
$token = $tokenResponse.access_token
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}
# Get the list of devices from Microsoft Defender
$url = "https://api.securitycenter.microsoft.com/api/machines"
$DefenderDevices = (Invoke-RestMethod -Method Get -Uri $url -Headers $headers).value
# Get the list of vCenter devices from the webhook data
if ($WebhookData.RequestBody) {
$vCenterDevices = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
}
else {
Write-Output "No data in requestbody!"
}
# Extract a hashset of all (lowercase) hostnames found in defender devices
$defendernames = $DefenderDevices | ForEach-Object {
# Get only the first part of the DNS name (before the first dot), and lowercase it
$defenderhost = $_.computerDnsName -split '\.' | Select-Object -First 1
$defenderhost.ToLower()
} | Select-Object -Unique
# Now compare each vCenter name (case-insensitive) against the hashset
$missingInDefender = $vCenterDevices | Where-Object {
$vcenterName = $_.name.ToLower()
-not ($defendernames -contains $vcenterName)
}
#Date formating
$todaystring = Get-Date -Format "dd.MM.yyyy hh:mm:ss"
$today = [datetime]::ParseExact($todaystring, "dd.MM.yyyy HH:mm:ss", $null)
# Loop through each missing device and create a ticket in Jira
foreach($mDefender in $missingInDefender){
$summarySearch = "$($mDefender.name)"
$jql = [System.Web.HttpUtility]::UrlEncode("summary ~ `"$summarySearch`"")
# Construct the API URL
$uri = "https://contoso.atlassian.net/rest/api/3/search?jql=$jql"
$ticket = @()
$ticket = Invoke-RestMethod -Method get -Uri $uri -Headers $headersJira | Where-Object{$_.issues.fields.status.name -notlike "Done"}
# Check if the ticket already exists
If(!$ticket){
$startDateString = get-date $mDefender.CreateDate -Format "dd.MM.yyyy hh:mm:ss"
$startDate = [datetime]::ParseExact($startDateString, "dd.MM.yyyy HH:mm:ss", $null)
if ((New-TimeSpan -start $startDate -End $today).days -ge $threshold){
$body = @"
{"fields":{"project":{"id":"10036"},"issuetype":{"id":"10002"},"summary":"$($mDefender.name) mangler i Defender","description":{"version":1,"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"$($mDefender.name) $($mDefender.createdate) $($mDefender.notes)"}]}]},"customfield_10181":{"id":"10348","value":"Operations Team"},"components":[],"fixVersions":[],"priority":{"id":"3","name":"Medium""},"labels":["VCenterDefender"]},"update":{},"watchers":[]}
"@
Invoke-RestMethod -Uri "https://contoso.atlassian.net/rest/api/3/issue/" -Method POST -Headers $headersJira -Body $body
}
else{Write-Output "There is already a ticket for $($mDefender.name)"}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment