I had built a pipeline which scans the Keyvaults and sends a Microsoft Teams notification using Webhook(Eonos Office Webhook) incase any Key/Certificate has expired/about to Expire. And the pipeline worked perfectly, however since O365 connectors are deing depreciated, I am forced to use Microsoft Workflows to post a message from a Webhook Request.
For that I created a Workflow which 'Post to a channel when a webhook request is received' but when I replaced my current Eonos WebhookURL with the new Workflow URL, my notification layout is completely changed and I am getting more of a text than a proper notification.
This is how my notifications used to look like:
and I just replaced the URL with the new Workflow Webhook URl, I am getting the following output:
So, It is just printing the value that it is being provided.
This is my Workflow Configuration:
and this is how I am sending the Webhook request from my Powershell skript:
and this is my Send-Notification function:
I believe that I need to change the configuration of my Flow (maybe) but I am not sure. Please help me with this :')
update from 18.09.2024:
Now I am get the links (of the secrets) as a Text instead of clickable links eventhough I enabled the Code view in the message:
and this is how I am getting the notification now:
Do you know how to solve this?
when I save it in code view and refresh it and check it again, it shows me in normal mode:
this is my code, where I check secret and create the URL for it:
function Check-Secrets {
param(
[string]$keyVault,
[string]$globalSubscription,
[string]$resourceGroup
)
$expiringSecrets = @()
$noExpirySecrets = @()
$secrets = az keyvault secret list --vault-name $keyVault --query "[].id" -o tsv 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Output "Unable to access Key Vault: $keyVault"
$global:inaccessibleKeyVaults += $keyVault
continue
}
foreach ($secret in $secrets) {
$secretAttributesJson = az keyvault secret show --id $secret --query "attributes" -o json
$secretAttributes = $secretAttributesJson | ConvertFrom-Json
$secretName = az keyvault secret show --id $secret --query "name" -o tsv
$secretUrl = "https://portal.azure.com/#view/Microsoft_Azure_KeyVault/ListObjectVersionsRBACBlade/~/overview/objectType/secrets/objectId/https%3A%2F%2F$keyVault.vault.azure.net%2Fsecrets%2F$secretName/vaultResourceUri/%2Fsubscriptions%2F$globalSubscription%2FresourceGroups%2F$resourceGroup%2Fproviders%2FMicrosoft.KeyVault%2Fvaults%2F$keyVault/vaultId/%2Fsubscriptions%2F$globalSubscription%2FresourceGroups%2F$resourceGroup%2Fproviders%2FMicrosoft.KeyVault%2Fvaults%2F$keyVault"
if ($null -ne $secretAttributes.expires -and $secretAttributes.expires -ne '') {
$expiryDate = [DateTime]::Parse($secretAttributes.expires)
$oneMonthFromNow = (Get-Date).AddMonths(1)
if ($expiryDate -lt $oneMonthFromNow) {
$expiringSecrets += "Secret ID: [$secret]($secretUrl), Expiry Date: $expiryDate"
}
}
else {
$noExpirySecrets += "Secret ID: [$secret]($secretUrl)"
}
}
return @{
"ExpiringSecrets" = $expiringSecrets
"NoExpirySecrets" = $noExpirySecrets
}
}
and this is how I called the function:
$expiringSecretsMessage = if ($expiringSecrets.Count -gt 0) { "The following secrets are expiring:<br />" + ($expiringSecrets -join "<br />") }
$noExpirySecretsMessage = if ($noExpirySecrets.Count -gt 0) { "The following secrets have no expiry date:<br />" + ($noExpirySecrets -join "<br />") }
$expiringCertificatesMessage = if ($expiringCertificates.Count -gt 0) { "The following certificates are expiring:<br />" + ($expiringCertificates -join "<br />") }
$noExpiryCertificatesMessage = if ($noExpiryCertificates.Count -gt 0) { "The following certificates have no expiry date:<br />" + ($noExpiryCertificates -join "<br />") }
Send-Notification -keyVault $keyVault -WebhookURL $WebhookURL -messageParts @($expiringSecretsMessage, $noExpirySecretsMessage, $expiringCertificatesMessage, $noExpiryCertificatesMessage)
As far as I have tested, to send clickable hyperlink as parts of your Teams message requires your context to use the valid HTML hyperlink syntax like Secret ID: <a href="URL">ALIAS</a>
. Here is a sample YAML pipeline that is to generate the webhook payload with hyperlink syntax.
pool:
vmImage: ubuntu-latest
variables:
myTestKV: xxxmytestkvxxx
TeamsWebhookURL: https://xxxxxx
steps:
- task: AzureCLI@2
inputs:
azureSubscription: 'ARMSvcCnnSub0'
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
$myTestKV = "$(myTestKV)"
# Fetch secrets using Azure CLI command
$secrets = az keyvault secret list --id https://$myTestKV.vault.azure.net/ | ConvertFrom-Json
$currentDate = (Get-Date).ToUniversalTime()
$expiringSecrets = @()
$noExpirySecrets = @()
foreach ($secret in $secrets) {
$expires = $secret.attributes.expires
if ($expires) {
$expiryDate = [datetime]::Parse($expires)
$daysRemaining = ($expiryDate - $currentDate).Days
if ($daysRemaining -le 30) {
$expiringSecrets += $secret
}
} else {
$noExpirySecrets += $secret
}
}
Write-Output "expiringSecrets - $($expiringSecrets | ConvertTo-Json -Depth 100)"
Write-Output "noExpirySecrets - $($noExpirySecrets | ConvertTo-Json -Depth 100)"
$expiringSecretsText = ""
foreach ($secret in $expiringSecrets) {
$expiryDate = [datetime]::Parse($secret.attributes.expires).ToUniversalTime().ToString("MM/dd/yyyy HH:mm:ss")
$expiringSecretsText += "Secret ID: <a href=`\`"$($secret.id)`\`">$($secret.name)</a>Expiry Date (UTC): <span style=`\`'color: red;`\`'>$expiryDate</span><br />"
}
$noExpirySecretsText = ""
foreach ($secret in $noExpirySecrets) {
$noExpirySecretsText += "Secret ID: <a href=`\`"$($secret.id)`\`">$($secret.name)</a><br />"
}
$testMessageJSON = @"
{
"text": "<b>The following secrets are expiring:</b><br />$expiringSecretsText<br /><b>The following secrets have no expiry date:</b><br />$noExpirySecretsText<br />",
"title": "Key Vault: $myTestKV"
}
"@
Write-Output $testMessageJSON
$WebhookURL = "$(TeamsWebhookURL)"
Write-Host "WebhookURL - $WebhookURL"
Invoke-RestMethod -Method Post -Uri $WebhookURL -Body $testMessageJSON -ContentType 'application/json'
Sample webhook payload
{
"text": "<b>The following secrets are expiring:</b><br />Secret ID: <a href=\"https://xxxmytestkvxxx.vault.azure.net/secrets/secret1\">secret1</a>Expiry Date (UTC): <span style=\'color: red;\'>09/22/2024 16:00:00</span><br />Secret ID: <a href=\"https://xxxmytestkvxxx.vault.azure.net/secrets/secret3\">secret3</a>Expiry Date (UTC): <span style=\'color: red;\'>09/30/2024 15:59:59</span><br /><br /><b>The following secrets have no expiry date:</b><br />Secret ID: <a href=\"https://xxxmytestkvxxx.vault.azure.net/secrets/secret2\">secret2</a><br />Secret ID: <a href=\"https://xxxmytestkvxxx.vault.azure.net/secrets/secret4\">secret4</a><br /><br />",
"title": "Key Vault: xxxmytestkvxxx"
}