Last active
July 12, 2024 12:02
-
-
Save lsgalves/f4173c52cfbbfbcec63b1434c9a05e49 to your computer and use it in GitHub Desktop.
Skymail DNS script for win-acme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Add or remove a DNS TXT record to Skymail | |
.DESCRIPTION | |
Note that this script is intended to be run via the install script plugin from win-acme via the batch script wrapper. | |
As such, we use positional parameters to avoid issues with using a dash in the cmd line. | |
.PARAMETER RecordName | |
The fully qualified name of the TXT record. | |
.PARAMETER TxtValue | |
The value of the TXT record. | |
.PARAMETER SkymailEmail | |
The Skymail user email. | |
.PARAMETER SkymailPassword | |
The Skymail user password. | |
.PARAMETER SkymailSecretKey | |
The Skymail user secret key. | |
.PARAMETER ExtraParams | |
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports. | |
.EXAMPLE | |
SkymailDNS.ps1 create {RecordName} {Token} {vault://json/skymail_email} {vault://json/skymail_password} {vault://json/skymail_secret} | |
SkymailDNS.ps1 delete {RecordName} {Token} {vault://json/skymail_email} {vault://json/skymail_password} {vault://json/skymail_secret} | |
.NOTES | |
#> | |
param( | |
[string]$Task, | |
[string]$RecordName, | |
[string]$TxtValue, | |
[string]$SkymailEmail, | |
[string]$SkymailPassword, | |
[string]$SkymailSecretKey | |
) | |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | |
############################ | |
# Helper Functions | |
############################ | |
Function Base64UrlEncode { | |
param ($str) | |
$base64 = [Convert]::ToBase64String($str) | |
$base64 = $base64.TrimEnd('=').Replace('+', '-').Replace('/', '_') | |
return $base64 | |
} | |
Function HMACSHA256 { | |
param ($data, $key) | |
$hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256 | |
$hmacsha256.Key = [Text.Encoding]::UTF8.GetBytes($key) | |
$hashBytes = $hmacsha256.ComputeHash([Text.Encoding]::UTF8.GetBytes($data)) | |
return $hashBytes | |
} | |
Function Get-JWT { | |
param ( | |
[string]$email, | |
[string]$password, | |
[string]$secretKey | |
) | |
$form = @{ | |
username = $email | |
password = $password | |
} | |
$response = Invoke-RestMethod -Uri "https://api.skymail.net.br/v1/auth/login" -Method Post -Body $form | |
$header = @{ | |
alg = 'HS256' | |
typ = 'JWT' | |
} | |
$headerJson = $header | ConvertTo-Json -Compress | |
$headerBytes = [Text.Encoding]::UTF8.GetBytes($headerJson) | |
$headerEncoded = Base64UrlEncode $headerBytes | |
$payloadJson = $response.data | ConvertTo-Json -Compress | |
$payloadBytes = [Text.Encoding]::UTF8.GetBytes($payloadJson) | |
$payloadEncoded = Base64UrlEncode $payloadBytes | |
$headerPayload = "$headerEncoded.$payloadEncoded" | |
$secretKeyBytes = [System.Convert]::FromBase64String($secretKey) | |
$decodedSecretKey = [System.Text.Encoding]::UTF8.GetString($secretKeyBytes) | |
$signature = HMACSHA256 $headerPayload $decodedSecretKey | |
$signatureEncoded = Base64UrlEncode $signature | |
return "$headerPayload.$signatureEncoded" | |
} | |
############################ | |
Function Add-DnsTxt { | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory,Position=0)] | |
[string]$RecordName, | |
[Parameter(Mandatory,Position=1)] | |
[string]$TxtValue, | |
[Parameter(Mandatory,Position=2)] | |
[string]$SkymailEmail, | |
[Parameter(Mandatory,Position=3)] | |
[string]$SkymailPassword, | |
[Parameter(Mandatory,Position=4)] | |
[string]$SkymailSecretKey, | |
[Parameter(ValueFromRemainingArguments)] | |
$ExtraParams | |
) | |
# get the Skymail API JWT | |
$apiBase = "https://api.skymail.net.br/v1" | |
$jwt = Get-JWT $SkymailEmail $SkymailPassword $SkymailSecretKey | |
$Headers = @{ Authorization = "Bearer $jwt" } | |
# find the domain/zone associated with this record | |
$pieces = $RecordName.Split('.') | |
for ($i=0; $i -lt ($pieces.Count-1); $i++) { | |
$zoneTest = $pieces[$i..($pieces.Count-1)] -join '.' | |
try { | |
$Zone = Invoke-RestMethod "$apiBase/dns?filters[name]=$($zoneTest)" ` | |
-Method Get -Headers $Headers | |
} catch { continue } | |
if ($Zone.data) { | |
$domain = $zoneTest | |
Write-Verbose "Found $domain zone" | |
break | |
} | |
} | |
if (-not $domain) { throw "Unable to find zone for $RecordName" } | |
# grab the relative portion of the fqdn | |
$recShort = ($RecordName -ireplace [regex]::Escape($domain), [string]::Empty).TrimEnd('.') | |
# check for existing record | |
$Records = Invoke-RestMethod "$apiBase/dns/$domain/entry?filters[type]=TXT" ` | |
-Method Get -Headers $Headers | |
$rec = $Records.data | Where-Object { $_.type -eq 'TXT' -and $_.name -eq $RecordName -and $_.value -eq $TxtValue } | |
if ($rec) { | |
Write-Debug "Record $RecordName already contains $TxtValue. Nothing to do." | |
} else { | |
# add it | |
Write-Verbose "Adding a TXT record for $RecordName with value $TxtValue" | |
$body = @{ | |
type = "TXT" | |
name = $RecordName | |
value = $TxtValue | |
ttl = 300 | |
} | ConvertTo-Json | |
Write-Debug $body | |
try { | |
Invoke-RestMethod "$apiBase/dns/$domain/entry" -Method Post ` | |
-Body $body -ContentType 'application/json' -Headers $Headers | |
} catch { | |
throw "Failed to add TXT record for $RecordName with value $TxtValue" | |
} | |
} | |
<# | |
.SYNOPSIS | |
Add a DNS TXT record to Skymail. | |
.DESCRIPTION | |
Add a DNS TXT record to Skymail. | |
.PARAMETER RecordName | |
The fully qualified name of the TXT record. | |
.PARAMETER TxtValue | |
The value of the TXT record. | |
.PARAMETER SkymailEmail | |
The Skymail user email. | |
.PARAMETER SkymailPassword | |
The Skymail user password. | |
.PARAMETER SkymailSecretKey | |
The Skymail user secret key. | |
.PARAMETER ExtraParams | |
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports. | |
.EXAMPLE | |
Add-DnsTxt '_acme-challenge.example.com' 'txtvalue' -SkymailEmail 'user@example.com' -SkymailPassword 'xxxxxxxx' -SkymailSecretKey 'xxxxxxxx' | |
Adds a TXT record for the specified site with the specified value. | |
#> | |
} | |
Function Remove-DnsTxt { | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory,Position=0)] | |
[string]$RecordName, | |
[Parameter(Mandatory,Position=1)] | |
[string]$TxtValue, | |
[Parameter(Mandatory,Position=2)] | |
[string]$SkymailEmail, | |
[Parameter(Mandatory,Position=3)] | |
[string]$SkymailPassword, | |
[Parameter(Mandatory,Position=4)] | |
[string]$SkymailSecretKey, | |
[Parameter(ValueFromRemainingArguments)] | |
$ExtraParams | |
) | |
# get the Skymail API JWT | |
$apiBase = "https://api.skymail.net.br/v1" | |
$jwt = Get-JWT $SkymailEmail $SkymailPassword $SkymailSecretKey | |
$Headers = @{ Authorization = "Bearer $jwt" } | |
# find the domain/zone associated with this record | |
$pieces = $RecordName.Split('.') | |
for ($i=0; $i -lt ($pieces.Count-1); $i++) { | |
$zoneTest = $pieces[$i..($pieces.Count-1)] -join '.' | |
try { | |
$Zone = Invoke-RestMethod "$apiBase/dns?filters[name]=$($zoneTest)" ` | |
-Method Get -Headers $Headers | |
} catch { continue } | |
if ($Zone.data) { | |
$domain = $zoneTest | |
Write-Verbose "Found $domain zone" | |
break | |
} | |
} | |
if (-not $domain) { throw "Unable to find zone for $RecordName" } | |
# grab the relative portion of the fqdn | |
$recShort = ($RecordName -ireplace [regex]::Escape($domain), [string]::Empty).TrimEnd('.') | |
# check for existing record | |
$Records = Invoke-RestMethod "$apiBase/dns/$domain/entry?filters[type]=TXT" ` | |
-Method Get -Headers $Headers | |
$rec = $Records.data | Where-Object { $_.type -eq 'TXT' -and $_.name -eq $RecordName -and $_.value -eq $TxtValue } | |
if ($rec) { | |
# remove it | |
Write-Verbose "Removing TXT record for $RecordName with value $TxtValue" | |
try { | |
Invoke-RestMethod "$apiBase/dns/$domain/entry/$($rec.id)" -Method Delete ` | |
-Headers $Headers | |
} catch { | |
throw "Failed to delete TXT record for $RecordName with value $TxtValue" | |
} | |
} else { | |
Write-Debug "Record $RecordName with value $TxtValue doesn't exist. Nothing to do." | |
} | |
<# | |
.SYNOPSIS | |
Remove a DNS TXT record to Skymail. | |
.DESCRIPTION | |
Remove a DNS TXT record to Skymail. | |
.PARAMETER RecordName | |
The fully qualified name of the TXT record. | |
.PARAMETER TxtValue | |
The value of the TXT record. | |
.PARAMETER SkymailEmail | |
The Skymail user email. | |
.PARAMETER SkymailPassword | |
The Skymail user password. | |
.PARAMETER SkymailSecretKey | |
The Skymail user secret key. | |
.PARAMETER ExtraParams | |
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports. | |
.EXAMPLE | |
Remove-DnsTxt '_acme-challenge.example.com' 'txtvalue' -EDToken 'xxxxxxxx' -EDKey 'xxxxxxxx' | |
Removes a TXT record for the specified site with the specified value. | |
#> | |
} | |
function Save-DnsTxt { | |
[CmdletBinding()] | |
param( | |
[Parameter(ValueFromRemainingArguments)] | |
$ExtraParams | |
) | |
<# | |
.SYNOPSIS | |
Not required. | |
.DESCRIPTION | |
This provider does not require calling this function to commit changes to DNS records. | |
.PARAMETER ExtraParams | |
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports. | |
#> | |
} | |
if ($Task -eq 'create'){ | |
Add-DnsTxt $RecordName $TxtValue $SkymailEmail $SkymailPassword $SkymailSecretKey | |
} | |
if ($Task -eq 'delete'){ | |
Remove-DnsTxt $RecordName $TxtValue $SkymailEmail $SkymailPassword $SkymailSecretKey | |
} | |
# API Docs | |
# https://skymail.docs.apiary.io/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment