Skip to content

Instantly share code, notes, and snippets.

@lsgalves
Last active July 12, 2024 12:02
Show Gist options
  • Save lsgalves/f4173c52cfbbfbcec63b1434c9a05e49 to your computer and use it in GitHub Desktop.
Save lsgalves/f4173c52cfbbfbcec63b1434c9a05e49 to your computer and use it in GitHub Desktop.
Skymail DNS script for win-acme
<#
.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