Fortunately I've got great friends and Mitch Steiner had been messing with AudioCodes new API to pull some interesting metrics for our T2M Cloud and he let me know that he stumbled upon a way to pull the .ini configuration using the REST API. The new REST API reduced the amount of code to do a backup down to literally one line. Now obviously it would be cool to have a script that detected which AudioCodes version it was connected to, so it is more than just one line in the script below. I also found a way to "Burn" the configuration on 7.0 and 7.2 using the API. So that is part of the script and executes just before backup.
Couple of key items before you run the script below.
- If you are running on a Windows 7 or other workstation you'll need to set your PowerShell Execution Policy.
- Next you will need to install a package called cURL that is a command line tool for interacting with web pages. It is required to work with the Forms Based Auth that audiocodes uses. I used a new tool to install it called Chocolatey, which is the equivalent of RPM packages for Windows. Here is the page for cURL (http://chocolatey.org/packages/curl) and here is the main page for Chocolatey (http://chocolatey.org/)
- PowerShell has an alias for curl that you'll need to remove. The command is Remove-Item alias:curl
Without further adieu... I give you the AudioCodes backup script that will backup any 6.4, 6.6, 6.8, 7.0, or 7.2 AudioCodes Gateway/SBC.
# Script to Backup AudioCodes Gateways# Created By Jonathan McKinney (blog.ucomsgeek.com)# Disclaimer: You running this script means you won't blame Jonathan McKinney or his employer if this breaks your stuff. This script is provided AS IS without warranty of any kind.
# User Modifiable Variables
$username = "Admin"
$password = "Admin"
$address = "m4000.ucomsgeek.com"
$backuppath = "c:\scripts\backups\"
# Variable Initialization
$filename = $null
$statuscodeeval = $null
#Function to detect if Forms Auth is present
function DetectAuthType ($ad)
{
$loginurl = $null
$loginurl = "http://" + $ad + "/api"
$statuscode = curl -o null.txt $loginurl -w '%{http_code}'
If ($statuscode -eq "404")
{
$loginurl = "http://" + $ad + "/"
$statuscode = curl -o null.txt $loginurl -w '%{http_code}'
Write-host `r`n "Status Code " $statuscode
If ($statuscode -eq "401")
{
$statuscodeeval = "basic"
}
ElseIf ($statuscode -eq "203")
{
$statuscodeeval = "forms"
}
Else
{
$statuscodeeval = "neither"
}
}
ElseIf ($statuscode -eq "401")
{
$statuscodeeval = "api"
}
Return $statuscodeeval
Remove-Item null.txt
}
# Function to Authenticate with Forms Auth
function AuthenticateForms ($un, $pw, $ad)
{
$login1sregex = "\<s\>(\d*)\<\/s\>"
$login1rregex = "\<r\>(.*)\<\/r\>"
$a1 = $null
$loginusername = $null
$loginurl = $null
$login1webpage = $null
$login1spattern = $null
$login1rpattern = $null
$hashByteArray1 = $null
$hashByteArray2 = $null
$passwordhash = $null
$resultwebpage = $null
$formsbasedauth = $null
Write-Host `r`n 'Forms Authentication' `r`n
$login1username = "c1=" + $un
$loginurl = "http://" + $ad + "/UE/Login"
$login1webpage = curl $loginurl --data-urlencode "t=1" `
--data-urlencode "c0=0" `
--data-urlencode $login1username `
--header "X-Requested-With: XMLHttpRequest" `
-c cookiejar.txt `
--header "Cookie: aclogname=; C2=ct" `
--user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
$login1spattern = $login1webpage -split "`n" | Select-String -pattern $login1sregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }
$login1spattern = "s=" + $login1spattern
$login1rpattern = $login1webpage -split "`n" | Select-String -pattern $login1rregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }
$cryptoServiceProvider = [System.Security.Cryptography.SHA256CryptoServiceProvider]
$hashAlgorithm = New-Object $cryptoServiceProvider
$hashByteArray1 = $hashAlgorithm.ComputeHash($([Char[]]$password))
foreach ($byte in $hashByteArray1)
{
$a1 += "{0:x2}" -f $byte
}
$a2 = $username + ":" + $login1rpattern + ":" + $a1
$hashByteArray2 = $hashAlgorithm.ComputeHash($([Char[]]$a2))
foreach ($byte in $hashByteArray2)
{
$passwordhash += "{0:x2}" -f $byte
}
$passwordhash = "c1=" + $passwordhash
$resultwebpage = curl $loginurl --data-urlencode "t=1" `
--data-urlencode $login1spattern `
--data-urlencode "c0=1" `
--data-urlencode $passwordhash `
--header "X-Requested-With: XMLHttpRequest" `
-c cookiejar.txt `
--header "Cookie: aclogname=; C2=ct" `
--user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
}
# Function to Backup Gateway WITHOUT Forms Auth
function BackupBasic ($un, $pw, $ad, $path)
{
$regex = "BOARD.*\.ini"
$webclient = $null
$configurl = $null
$backupurl = $null
$webpage = $null
$pattern = $null
$backupfilename = $null
$webclient = new-object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($un, $pw)
Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $ad + "/ConfigurationFile"
$webpage = $webclient.DownloadString($configurl)
$pattern = $webpage -split "`n" | Select-String -pattern $regex -Allmatches | % { $_.Matches | % { $_.Value } }
Write-Host `r`n 'Detected Board Filename ' $pattern
Write-Host `r`n 'Backing up ' $ad `r`n
$backupurl = "http://" + $ad + "/FS/" + $pattern
$backupfilename = $path + $pattern
$webclient.DownloadFile($backupurl,$backupfilename)
Write-Host `r
}
# Function to Detect the Backup Filename with Forms Auth for the Audiocodes Configuration File
function DetectFilenameForms ($ad)
{
$fnregex = "BOARD.*\.ini"
$configurl = $null
$fnpat = $null
$configwebpage = $null
Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $ad + "/ConfigurationFile"
$configwebpage = curl $configurl -b cookiejar.txt
$fnpat = $configwebpage -split "`n" | Select-String -pattern $fnregex -Allmatches | % { $_.Matches | % { $_.Value } }
Write-Host `r`n 'Detected Board Filename ' $fnpat
return $fnpat
}
# Function to Backup Gateway with Forms Auth
function BackupGatewayForms ($ad, $path, $fn)
{
$backupurl = $null
$backupfilename = $null
Write-Host `r`n 'Backing up ' $ad `r`n
$backupurl = "http://" + $ad + "/FS/" + $fn
$backupfilename = $path + $fn
curl -o $backupfilename $backupurl -b cookiejar.txt
Write-Host `r
}
function BackupGatewayAPI ($un, $pw, $ad, $path)
{
$backupurlsc = $null
$backupurlini = $null
$backupfilename = $null
$securepw = $null
$cred = $null
$backupurlsc = "http://" + $ad + "/api/v1/actions/saveConfiguration"
$backupurlini = "http://" + $ad + "/api/v1/files/ini"
$addressfilename = $ad.Replace(“.”,”-”)
$backupfilename = $path + "BOARD.ini"
Write-Host $backupfilename
$securepw = ConvertTo-SecureString -String $pw -AsPlainText -Force
$cred = new-object System.Management.Automation.PSCredential ($un, $securepw)
Invoke-RestMethod $backupurlsc -Method post -Credential $cred
Invoke-RestMethod $backupurlini -Method get -Credential $cred -OutFile $backupfilename -verbose
Write-Host `r
}
# Function to Logoff Audiocodes with Forms Auth after finishing work
function LogoffForms ($ad)
{
$logoffurl = $null
$logoffwebpage = $null
$logoffurl = "http://" + $ad + "/PressLogOff"
$logoffwebpage = curl $logoffurl -b cookiejar.txt
Remove-Item cookiejar.txt
}
# Main Script
$formsbasedauth = DetectAuthType $address
if ($formsbasedauth -eq "forms")
{
AuthenticateForms $username $password $address
$filename = DetectFilenameForms $address
BackupGatewayForms $address $backuppath $filename
LogoffForms $address
}
ElseIf ($formsbasedauth -eq "basic")
{
BackupBasic $username $password $address $backuppath
}
ElseIf ($formsbasedauth -eq "api")
{
BackupGatewayAPI $username $password $address $backuppath
}
Else
{
Write-Host "Something went really wrong... couldn't detect Authentication type... Might I suggest Wireshark"
}
# User Modifiable Variables
$username = "Admin"
$password = "Admin"
$address = "m4000.ucomsgeek.com"
$backuppath = "c:\scripts\backups\"
# Variable Initialization
$filename = $null
$statuscodeeval = $null
#Function to detect if Forms Auth is present
function DetectAuthType ($ad)
{
$loginurl = $null
$loginurl = "http://" + $ad + "/api"
$statuscode = curl -o null.txt $loginurl -w '%{http_code}'
If ($statuscode -eq "404")
{
$loginurl = "http://" + $ad + "/"
$statuscode = curl -o null.txt $loginurl -w '%{http_code}'
Write-host `r`n "Status Code " $statuscode
If ($statuscode -eq "401")
{
$statuscodeeval = "basic"
}
ElseIf ($statuscode -eq "203")
{
$statuscodeeval = "forms"
}
Else
{
$statuscodeeval = "neither"
}
}
ElseIf ($statuscode -eq "401")
{
$statuscodeeval = "api"
}
Return $statuscodeeval
Remove-Item null.txt
}
# Function to Authenticate with Forms Auth
function AuthenticateForms ($un, $pw, $ad)
{
$login1sregex = "\<s\>(\d*)\<\/s\>"
$login1rregex = "\<r\>(.*)\<\/r\>"
$a1 = $null
$loginusername = $null
$loginurl = $null
$login1webpage = $null
$login1spattern = $null
$login1rpattern = $null
$hashByteArray1 = $null
$hashByteArray2 = $null
$passwordhash = $null
$resultwebpage = $null
$formsbasedauth = $null
Write-Host `r`n 'Forms Authentication' `r`n
$login1username = "c1=" + $un
$loginurl = "http://" + $ad + "/UE/Login"
$login1webpage = curl $loginurl --data-urlencode "t=1" `
--data-urlencode "c0=0" `
--data-urlencode $login1username `
--header "X-Requested-With: XMLHttpRequest" `
-c cookiejar.txt `
--header "Cookie: aclogname=; C2=ct" `
--user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
$login1spattern = $login1webpage -split "`n" | Select-String -pattern $login1sregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }
$login1spattern = "s=" + $login1spattern
$login1rpattern = $login1webpage -split "`n" | Select-String -pattern $login1rregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }
$cryptoServiceProvider = [System.Security.Cryptography.SHA256CryptoServiceProvider]
$hashAlgorithm = New-Object $cryptoServiceProvider
$hashByteArray1 = $hashAlgorithm.ComputeHash($([Char[]]$password))
foreach ($byte in $hashByteArray1)
{
$a1 += "{0:x2}" -f $byte
}
$a2 = $username + ":" + $login1rpattern + ":" + $a1
$hashByteArray2 = $hashAlgorithm.ComputeHash($([Char[]]$a2))
foreach ($byte in $hashByteArray2)
{
$passwordhash += "{0:x2}" -f $byte
}
$passwordhash = "c1=" + $passwordhash
$resultwebpage = curl $loginurl --data-urlencode "t=1" `
--data-urlencode $login1spattern `
--data-urlencode "c0=1" `
--data-urlencode $passwordhash `
--header "X-Requested-With: XMLHttpRequest" `
-c cookiejar.txt `
--header "Cookie: aclogname=; C2=ct" `
--user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
}
# Function to Backup Gateway WITHOUT Forms Auth
function BackupBasic ($un, $pw, $ad, $path)
{
$regex = "BOARD.*\.ini"
$webclient = $null
$configurl = $null
$backupurl = $null
$webpage = $null
$pattern = $null
$backupfilename = $null
$webclient = new-object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($un, $pw)
Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $ad + "/ConfigurationFile"
$webpage = $webclient.DownloadString($configurl)
$pattern = $webpage -split "`n" | Select-String -pattern $regex -Allmatches | % { $_.Matches | % { $_.Value } }
Write-Host `r`n 'Detected Board Filename ' $pattern
Write-Host `r`n 'Backing up ' $ad `r`n
$backupurl = "http://" + $ad + "/FS/" + $pattern
$backupfilename = $path + $pattern
$webclient.DownloadFile($backupurl,$backupfilename)
Write-Host `r
}
# Function to Detect the Backup Filename with Forms Auth for the Audiocodes Configuration File
function DetectFilenameForms ($ad)
{
$fnregex = "BOARD.*\.ini"
$configurl = $null
$fnpat = $null
$configwebpage = $null
Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $ad + "/ConfigurationFile"
$configwebpage = curl $configurl -b cookiejar.txt
$fnpat = $configwebpage -split "`n" | Select-String -pattern $fnregex -Allmatches | % { $_.Matches | % { $_.Value } }
Write-Host `r`n 'Detected Board Filename ' $fnpat
return $fnpat
}
# Function to Backup Gateway with Forms Auth
function BackupGatewayForms ($ad, $path, $fn)
{
$backupurl = $null
$backupfilename = $null
Write-Host `r`n 'Backing up ' $ad `r`n
$backupurl = "http://" + $ad + "/FS/" + $fn
$backupfilename = $path + $fn
curl -o $backupfilename $backupurl -b cookiejar.txt
Write-Host `r
}
function BackupGatewayAPI ($un, $pw, $ad, $path)
{
$backupurlsc = $null
$backupurlini = $null
$backupfilename = $null
$securepw = $null
$cred = $null
$backupurlsc = "http://" + $ad + "/api/v1/actions/saveConfiguration"
$backupurlini = "http://" + $ad + "/api/v1/files/ini"
$addressfilename = $ad.Replace(“.”,”-”)
$backupfilename = $path + "BOARD.ini"
Write-Host $backupfilename
$securepw = ConvertTo-SecureString -String $pw -AsPlainText -Force
$cred = new-object System.Management.Automation.PSCredential ($un, $securepw)
Invoke-RestMethod $backupurlsc -Method post -Credential $cred
Invoke-RestMethod $backupurlini -Method get -Credential $cred -OutFile $backupfilename -verbose
Write-Host `r
}
# Function to Logoff Audiocodes with Forms Auth after finishing work
function LogoffForms ($ad)
{
$logoffurl = $null
$logoffwebpage = $null
$logoffurl = "http://" + $ad + "/PressLogOff"
$logoffwebpage = curl $logoffurl -b cookiejar.txt
Remove-Item cookiejar.txt
}
# Main Script
$formsbasedauth = DetectAuthType $address
if ($formsbasedauth -eq "forms")
{
AuthenticateForms $username $password $address
$filename = DetectFilenameForms $address
BackupGatewayForms $address $backuppath $filename
LogoffForms $address
}
ElseIf ($formsbasedauth -eq "basic")
{
BackupBasic $username $password $address $backuppath
}
ElseIf ($formsbasedauth -eq "api")
{
BackupGatewayAPI $username $password $address $backuppath
}
Else
{
Write-Host "Something went really wrong... couldn't detect Authentication type... Might I suggest Wireshark"
}