Search This Blog

Wednesday, June 08, 2016

Powershell: Cloudflare autoupdate public IP and send SMS

We had a connection that ran our company VPN. The VPN was available on a couple of URLs. This connection also had a backup connection, so if the primary link failed it would swap to the backup. However this would change the IP address.
I wanted to make it so that the when the connection failed over the VPN URLs were updated.
The script below achieves that by updating the DNS records in cloudflare with the new public IP of the connection.
It looks at the public IP and then compares it to the record in dns, if the same do nothing. If different then update and send SMS
The SMS api maybe different for you depending on the company you use.
 
function Get-ScriptDirectory
{
    #Determine the folder in which the script lives.
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}
#[string]$CRLF
#needed to find the location of the script.
$scriptPath = Get-ScriptDirectory

[String]$scriptCurrentDateTime = Get-Date -format "yyyyMMddHHmmss"

$headers = @{
        'X-Auth-Key' = '<auth-key>';
        'X-Auth-Email' = '<email>';
        'Content-Type' = 'application/json'
    }

[string]$urlRequest = 'https://api.smscompanyurl.com/api-adv.php?';
[string]$smsUsername = '<username>';
[string]$smsPassword = '<password>';
[string]$smsNumbers = '<phonenumber1>,<phonenumber2>,<phonenumber3>';
[string]$smsFrom = '<Company Name>';
[string]$smsMessage = [uri]::EscapeDataString('Office IP Address has changed. Attempting auto update.');



$ZoneRecords = @(
'temp.contoso.com',
'tempytemp.contoso.com'
)

[string]$Zone = 'contoso.com';
[string]$cloudFlareApiBaseUrl = 'https://api.cloudflare.com/client/v4';
[string]$public_IP='';
[string]$public_IP='';


# Get Zone ID from cloudflare
    try 
    {
        $request = Invoke-WebRequest -Uri "${cloudFlareApiBaseUrl}/zones/?name=${Zone}" -Method 'GET' -Headers $headers
    }
    catch
    {
        $MyError = $_
        Throw $MyError
    }
    $zoneId = $(ConvertFrom-Json $request.Content).result[0].id


#Lookup external ip
    try 
    {
        $public_IP = (Invoke-RestMethod https://api.ipify.org?format=json).ip.trim()
    }
    catch
    {
        $MyError = $_
        Throw $MyError
    }
     

Foreach ($Element IN $ZoneRecords) {

    #GET record info from cloudflare
    #$RecordVPNweb = Invoke-WebRequest -Uri "${cloudFlareApiBaseUrl}/zones/${ZoneId}/dns_records/?name=${Element}" -Method 'GET' -Headers $headers
    try 
    {
        $RecordVPN = Invoke-RestMethod -Uri "${cloudFlareApiBaseUrl}/zones/${ZoneId}/dns_records/?name=${Element}" -Method 'GET' -Headers $headers -ContentType 'application/json'   
    }
    catch
    {
        $MyError = $_
        Throw $MyError
    }
    
    #When using webrequest need to convert from jason
    #$RecordVPN_ID = $(ConvertFrom-Json $RecordVPN.Content).result[0].id
    #$RecordVPN_IP = $(ConvertFrom-Json $RecordVPN.Content).result[0].content
    $RecordVPN_ID = $RecordVPN.result[0].id
    $RecordVPN_IP = $RecordVPN.result[0].content
    
    if ($RecordVPN_IP -ne $public_IP) {

        $smsMessage = $smsMessage + [uri]::EscapeDataString("Changing from $RecordVPN_IP to new $public_IP");
        $queryString = "username=$smsUsername&password=${smsPassword}&to=${smsNumbers}&from=${smsFrom}&message=${smsMessage}";
        ${urlRequest}+${queryString}
        [string]$textfileName = "$scriptPath\IPChanged$scriptCurrentDateTime.txt"
        
        try 
        {
            #send sms
            [String]$scriptIPChangeDateTime = Get-Date -format "yyyy-MM-dd HHmmss"
            [string]$textfileContent = "IP Change attempted at $scriptIPChangeDateTime : ${urlRequest}+${queryString}"
            out-file -filepath $textfileName -inputobject $textfileContent -encoding ASCII
            Invoke-RestMethod -Uri "${urlRequest}+${queryString}" -Method 'GET';   
        }
        catch
        {
            $MyError = $_
            Throw $MyError
        }

        $Data = @{
        'id' = "${RecordVPN_ID}";
        'type' = 'A';
        'name' = "${Element}";
        'content' = "${public_IP}";
        }
    
        # If it exists, UPDATE (PUT), if not, CREATE (POST)
        [string]$method = 'PUT';
        if ($RecordVPN.result.Count -eq 0) {
            $method = 'POST';
            $Data.Remove('id');
        }

        $DataJson = ConvertTo-Json $Data

        try 
        {
            $JSONResponse = Invoke-RestMethod -Uri "${cloudFlareApiBaseUrl}/zones/${ZoneId}/dns_records/${RecordVPN_ID}/" -Headers $Headers -Body $DataJson -Method "${method}" -ContentType 'application/json' -ErrorAction Stop
        }
        catch
        {
            $MyError = $_
            Throw $MyError
        }
       
    }
}

Share/Bookmark

No comments:

Post a Comment