Skip to content
adatum
  • Home
  •  About adatum
  •  Learn Azure Bicep
  •  SCOM Web API
Automation

Using OMS and Azure Functions to restart Azure Web…

  • 16/06/201707/01/2025
  • by Martin Ehrnst

From time to time I have had problems with this blog and other sites running in Azure. Occasionally they throw HTTP 5XX errors and when it doesnt fix it self I will have to restart the web app. By using Operations Management Suite (OMS)  with the web app analytics solution added, I created an alert calling an Azure Function to restart the affected web app. It’s keeping the sites up until I can get to the bottom of the problem or change provider.. Anyway, this is how I set it up.

 

Before we create the actual function we will we have a few dependencies.

  • OMS Workspace with the Web App Analytics enabled (currently in public preview) –Not Covered
  • Azure Function account –Not Covered
  • Azure AD application used for authentication

Create an application for authentication

In order to access and manage Azure resources from Azure Functions we need to create an application in Azure Active Directory and assign it the proper permissions. I Used Powershell to do this, but it’s perfectly fine to use the online console.

The script below will create a new application and assign it “web site contributor” role. If you need other security rights chose a different role.  You can read more about the built-in roles here

Please edit the script to your needs. You will need the App Id, app password and TenantId to use as variables in our function.

Login-AzureRmAccount

#Add azure application to use for authenication from azure function
$application = New-AzureRmADApplication -DisplayName "AUTH: Azure Function" -HomePage "http://yourwebsites/functions" -IdentifierUris "https://adatum.no/AzureFunctions" -Password "***********************************"
#Grab the application ID
$appid = $application.ApplicationId.Guid 

#create a service principal for the AAD app
New-AzureRmADServicePrincipal -ApplicationId $appid

#add a role to the newly created principal.
#I have chosen Web Site Contributor, but if you want to use anything else. please see https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles
New-AzureRmRoleAssignment -RoleDefinitionName 'Website Contributor' -ServicePrincipalName $appid

#Get the tenant ID
$TenantId = (Get-AzureRmSubscription -SubscriptionName "NAME").TenantId

Finished:

 

Setting up the Function app

First, create three environment variables in your function app containing your application ID, password and tenant id.

FunctionApp>settings>Manage Application Settings

 

I had appreciated examples of how to encrypt this password

Next, the actual code.

#Get input
$input = Get-Content $req -Raw | ConvertFrom-Json
$AppName = $input.appName
$ResourceGroup = $input.resourceGroupName

#Get user and password, create credential object
$User = $env:AzureFunctionAppID
$Pass = ConvertTo-SecureString -String $env:AzureFunctionAppPwd -AsPlainText -Force

$Credential = New-Object System.Management.Automation.PSCredential $user,$pass

#Login
Add-AzureRmAccount -Credential $Credential -TenantId $env:TennantId -ServicePrincipal

#Restart the web app and output state
Restart-AzureRmWebApp -name $AppName -ResourceGroupname $ResourceGroup
$Output = (Get-AzureRmWebApp -name $AppName).State
Out-File -Encoding Ascii -FilePath $res -inputObject $output

This Powershell function will use the environment variables/AAD application to login to your Azure environment and restart the WebApp provided in the input. I have set it up to require AppName and ResourceGroup (name) in the json post.

Send the following in the test pane to verify that the function works.

{
    "appName": "mywebApp",
    "resourceGroupName": "MyWebbAppResourceGroup"
}

There isn’t much response other than the (hopefully) “Running” status, but you can confirm everything in you activity log. The user initiated will be your application we created in the first step.

 

OMS Alert with Json payload

 

 

To automate the process, OMS need to trigger the function when too many 500-errors occur. Azure Web App Analytics (preview) in OMS already have views enabled for different error codes, response time etc, so you can use this for what ever you need. I wanted to restart a specific web app based on error 500’s. This is the search string I ended up with

Type:AzureMetrics ResourceId=*"/MICROSOFT.WEB/SITES/"* (MetricName=Requests OR MetricName=Http*) MetricName=Http5xx Resource=WEBAPPNAME

Based on that search result i created an alert sending a webhook with a custom Json payload

{ 
"appName": "mywebApp", 
"resourceGroupName": "MyWebbAppResourceGroup"
 }

 

OMS should now kick off your Azure Function and restart the website without your interaction. To verify you can use the acitivity log and OMS’ alert log.

 

Share this:

  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on X (Opens in new window) X
  • Click to share on Reddit (Opens in new window) Reddit
Automation

Sending SMS with Azure functions and Twilio

  • 23/12/201607/01/2025
  • by Martin Ehrnst

Update:

As pointed out by Tao Yang, storing the Twilio credentials in the script isnt exactly best practice.

pretty cool but the secret should at least be stored as application settings, not in clear text in the code. or even better – in Key Vault

— Tao Yang (@MrTaoYang) July 4, 2017

I have updated the script below to use Functions environment variables. You can create these from Settings>Manage Application settings 
[Fast publish]

Here the other day i “needed” to send a SMS when an alert was raised in Microsoft OMS. I already had a Twilio subscription so i developed a little script to send my self a text message. Later I put that script in a runbook in Azure Automation and called that from the alert. SMS received and it was all good.

Later the same evening i was trying out Azure Functions which let you run so called ‘server-less code’. Serverless or not, the code has to run on something, but you don’t need to maintain the infrastructure. I needed something to test Functions so i ported my Automation runbook in to a function.

The function accepts (in my environment) a webhook or sending a post with Json string.

And here is the code that does it. You will have to add your own Twilio config, but other than that it should work.

<#
    .DESCRIPTION
        Azure function sending SMS through Twilio.
        Depending on how you set up your function. This script will accept bot GET parameters through it's URL or a POST with JSON string sending phone and msg

        {
            "phone": "+4712345678",
            "msg": "www.adatum.no"
        }

        It will send the msg to the number you provide.

    .NOTES
        Requires an active twilio subscription and an azure functions container.
        Please add your Twilio sid, secret and phone number to the script

        Created by Martin Ehrnst
        www.adatum.no

    .CHANGELOG
        21.12.16: v1.0 initial release

#>

$requestBody = Get-Content $req -Raw | ConvertFrom-Json
$phone = $requestBody.phone
$msg = $requestBody.msg
$sid = $env:TwilioSID
$password = ConvertTo-SecureString -String $env:TwilioPASS -AsPlainText -Force
$uri = "https://api.twilio.com/2010-04-01/Accounts/$sid/Messages.json"
$from = $env:TwilioPhone

if ($req_query_phone) 
{
    $phone = $req_query_phone 
}

if ($req_query_msg) 
{
    $msg = $req_query_msg
}


$cred = New-Object System.Management.Automation.PsCredential($sid,$password)

$SMS = @{
    From=$from
    To=$phone
    Body=$Msg
}

$SMSEND = Invoke-RestMethod -Method Post -Uri $uri -Credential $Cred -Body $SMS
Out-File -Encoding Ascii -FilePath $res -inputObject "$smssend"

Here is a little example on how you configure your OMS alert to use it. The message contains a link to the alert search result.

Share this:

  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on X (Opens in new window) X
  • Click to share on Reddit (Opens in new window) Reddit
Azure

I have moved script logging to OMS

  • 15/12/201607/01/2025
  • by Martin Ehrnst

For some time I have “rewritten” my scripts to utilize variables, connections  and other assets in Azure automation. While doing this I have moved all script logging to the cloud as well.

previously all scripts were logging to a file or to the computers event log. I have some experience with sending custom data to OMS. Using their API i have sent weather data and the technique could easily be transferred to do my script logging.

I thought about  creating a module for this for a while, but luckily, the great Mr Tao Yang already did it and it is available on GitHub, PSGallery and in Azure automation. The only thing i had to do was wrap everything in a function and call that each time i needed a log entry sent from my scripts.

Based on Tao’s OMSDataInjection module. Here’s how my function looks like

<#
    .DESCRIPTION
        Function sends a entry to OMS Log analytics.
        Used to send script log entries to OMS in a 'one liner'


    .NOTES
        Requires Tao Yang's OMSDatainjection Module: https://github.com/tyconsulting/OMSDataInjection-PSModule/releases/tag/1.1.1
        Author: Martin Ehrnst
        www.adatum.no
    
    .CHANGELOG
        06.12.16: Initial function release
    
#>

param (
    [parameter(Mandatory=$true)]
    [string]$Message,
    [parameter(Mandatory=$true)]
    [ValidateSet('Information','Warning','ERROR')]
    [string]$Severity
    )

$LogEntry = @{
  ScriptName = scriptName
  Severity = $Severity
  RanAT = $env:COMPUTERNAME
  Message  = "$Message"
  LogTime  = [Datetime]::UtcNow
}

$SendLog= New-OMSDataInjection -OMSWorkSpaceId '**************' -PrimaryKey '********************************' -LogType 'test' -UTCTimeStampField 'LogTime' -OMSDataObject $LogEntry
}

The only thing you have to before you use it is to define your script name, OMSWorkspaceID, PrimaryKey and a LogType. When all is good. Call this each time you want to send a log entry

Send-LogEntry -Message "testing 123" -Severity Warning

Here is a script, from on prem to Azure Automation to run on a Hybrid worker using this function to do the logging.

Please note that since i run through azure automation i have created a connection object and reffeer to that using instead of specifying the ID and Key.

<#
    .NAME
        Close-OldSCOMAlerts.ps1


    .DESCRIPTION
        Closes SCOM alerts based on severity, resolution state, repeat count etc. Alter settings in the configuration regions.
        The script requires OpsMgr module and Azure automation. I Reccomend storing the credentials and variables as assets and run the script on a hybrid worker.
        If you want to run locally, change the script parameters and hard code the values.


    .NOTES
        Requires Operations Manager Module and Tao Yang's OMSDatainjection Module
        Author: Martin Ehrnst
        Version: 1.1 Initial (Azure automation) Release 28.11.16
        www.adatum.no
        www.intility.no
    
    .CHANGELOG
        08.12.16: Using Tao Yang's OMSDataInjectionModule to ship script logs to OMS
        Removed local logging
    
#>

#region Configuration
$ErrorActionPreference = "Continue"
#$VerbosePreference = "Continue" #Uncomment to see verbose output
[int]$RepeatCount = 2 #Alerts with less than x repeat count will close
[int]$AlertAgeHours = 3 #Alert Age (older gets closed)
[string]$AlertSeverity = "Information" #specify alert severity you want to close
[int]$ResolutionState = 0 #0 NEW
[int]$SetState = 255 #255 CLOSED
[string]$Comment = "Alert closed by script in azure automation" #Comment to set on the closed alerts
#endregion

#region Modules
Import-Module "C:\Program Files\WindowsPowerShell\Modules\OMSDataInjection\1.1.1\OMSDataInjection.psm1"

$module = Get-Module -Name OperationsManager
if (!$module){
    Write-Verbose "Could not find SCOM Module. Importing"
    Import-Module OperationsManager -Cmdlet Get-SCOMalert, New-SCOMManagementGroupConnection, Update-SCOMAlert, Set-SCOMAlert
    }
#endregion

#region OMSLogging
    $OMSWorkspace = Get-AutomationConnection 'I2-Intility-Test'
    
    
function Send-LogEntry{
<#
    .DESCRIPTION
        Function sends a entry to OMS Log analytics.
        Used to send script log entries to OMS in a 'one liner'


    .NOTES
        Requires Tao Yang's OMSDatainjection Module: https://github.com/tyconsulting/OMSDataInjection-PSModule/releases/tag/1.1.1
        Author: Martin Ehrnst
        www.adatum.no
        www.intility.no
    
    .CHANGELOG
        06.12.16: Initial function release
    
#>
param (
    [parameter(Mandatory=$true)]
    [string]$Message,
    [parameter(Mandatory=$true)]
    [ValidateSet('Information','Warning','ERROR')]
    [string]$Severity
    )

$LogEntry = @{
  ScriptName = 'Close-OldSCOMAlerts.ps1'
  Severity = $Severity
  RanAT = $env:COMPUTERNAME
  Message  = $Message
  LogTime  = [Datetime]::UtcNow
}

$SendLog= New-OMSDataInjection -OMSConnection $OMSWorkspace -LogType 'AutomationLogs' -UTCTimeStampField 'LogTime' -OMSDataObject $LogEntry

}
#endregion

Send-LogEntry -Message "Starting azure automation runbook to close old scom alerts" -Severity Information

#region AzureConfig
    
    $SCOMOperator = Get-AutomationPSCredential -Name 'AzureAutomationSCOMOperator'
    $SCOMManagementServer = Get-AutomationVariable -Name 'SCOMProdSDKServer'

#endregion

Try {
    #Connecting to SCOM management server
    Write-Verbose "Connecting to $ManagementServer"
    New-SCOMManagementGroupConnection -ComputerName $SCOMManagementServer -Credential $SCOMOperator
    }
Catch {
    Write-Error "$_.Exception.Message"

    Send-LogEntry -Message "$_.Exception.Message" -Severity ERROR
    }

#Actual alert work
$Date = (Get-Date).AddHours(-$AlertAgeHours).ToUniversalTime() #Setting Alert age and converting to UTC

$Alerts = Get-ScomAlert | where {$_.TimeRaised -lt $Date `
    -and $_.ResolutionState -eq $ResolutionState `
    -and $_.Severity -match $AlertSeverity `
    -and $_.RepeatCount -lt $RepeatCount `
    -and $_.IsMonitorAlert -eq $false
    }
if ($Alerts){
        $count = $alerts.Count
        Send-LogEntry -Message "Closing $count alerts" -Severity Information
       
        $alerts | Set-SCOMAlert -ResolutionState $SetState -Comment $Comment
        Send-LogEntry -Message "Finished - closed $count alerts" -Severity Information
        Write-Output "closed $count alerts"
    }
else{
    Write-Output "No old alerts to close. Exiting script"
    Send-LogEntry -Message "Finished. No alerts to close" -Severity Information
    }

 

Share this:

  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on X (Opens in new window) X
  • Click to share on Reddit (Opens in new window) Reddit

Posts pagination

1 2 3

Popular blog posts

  • Azure Application registrations, Enterprise Apps, and managed identities
  • Remediate Azure Policy with PowerShell
  • Using webhook in scom subscription (POC)
  • Access to Blob storage using Managed Identity in Logic Apps - by Nadeem Ahamed
  • Azure token from a custom app registration

Categories

Automation Azure Azure Active Directory Azure Bicep Azure DevOps Azure Functions Azure Lighthouse Azure Logic Apps Azure Monitor Azure Policy Community Conferences CSP Monitoring DevOps GitHub Guest blogs Infrastructure As Code Kubernetes Microsoft CSP MPAuthoring OMS Operations Manager Podcast Powershell Uncategorised Windows Admin Center Windows Server

Follow Martin Ehrnst

  • X
  • LinkedIn

RSS feed RSS - Posts

RSS feed RSS - Comments

Microsoft Azure MVP

Martin Ehrnst Microsoft Azure MVP
Adatum.no use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it. Cookie Policy
Theme by Colorlib Powered by WordPress