Plugins/AddrTools.ps1

function Get-CurrentPluginType { 'dns-01' }

function Add-DnsTxt {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory,Position=0)]
        [string]$RecordName,
        [Parameter(Mandatory,Position=1)]
        [string]$TxtValue,
        [Parameter(Mandatory)]
        [securestring]$AddrToolsSecret,
        [string]$AddrToolsHost='challenges.addr.tools',
        [Parameter(ValueFromRemainingArguments)]
        $ExtraParams
    )

    $secPlain = [pscredential]::new('a',$AddrToolsSecret).GetNetworkCredential().Password

    $queryParams = @{
        Uri = 'https://{0}' -f $AddrToolsHost
        Method = 'POST'
        Body = @{
            secret = 'REDACTED'
            txt = $TxtValue
        }
        Verbose = $false
        ErrorAction = 'Stop'
    }
    # log with redacted secret
    Write-Verbose "Adding a TXT record for $RecordName with value $TxtValue"
    Write-Debug "$($queryParams.Method) $($queryParams.Uri)`n$($queryParams.Body|ConvertTo-Json)"

    try {
        $queryParams.Body.secret = $secPlain
        $resp = Invoke-RestMethod @queryParams @script:UseBasic
        if (-not $resp.Trim() -eq 'OK') {
            Write-Warning "Addr.Tools returned: $($resp.Trim())"
        }
    } catch { throw }

    <#
    .SYNOPSIS
        Add a DNS TXT record to challenges.addr.tools
 
    .DESCRIPTION
        Description for challenges.addr.tools
 
    .PARAMETER RecordName
        The fully qualified name of the TXT record.
 
    .PARAMETER AddrToolsSecret
        The secret associated with your challenges.addr.tools subdomain.
 
    .PARAMETER AddrToolsHost
        If self-hosting, domain name of your challenges.addr.tools equivalent (e.g. challenges.example.com)
 
    .PARAMETER TxtValue
        The value of the TXT record.
 
    .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' 'txt-value'
 
        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)]
        [securestring]$AddrToolsSecret,
        [string]$AddrToolsHost='challenges.addr.tools',
        [Parameter(ValueFromRemainingArguments)]
        $ExtraParams
    )

    $secPlain = [pscredential]::new('a',$AddrToolsSecret).GetNetworkCredential().Password

    $queryParams = @{
        Uri = 'https://{0}' -f $AddrToolsHost
        Method = 'DELETE'
        Body = @{
            secret = 'REDACTED'
            txt = $TxtValue
        }
        Verbose = $false
        ErrorAction = 'Stop'
    }
    # log with redacted secret
    Write-Verbose "Deleting $RecordName with value $TxtValue"
    Write-Debug "$($queryParams.Method) $($queryParams.Uri)`n$($queryParams.Body|ConvertTo-Json)"

    try {
        $queryParams.Body.secret = $secPlain
        $resp = Invoke-RestMethod @queryParams @script:UseBasic
        if (-not $resp.Trim() -eq '') {
            Write-Warning "Addr.Tools returned: $($resp.Trim())"
        }
    } catch { throw }

    <#
    .SYNOPSIS
        Remove a DNS TXT record from <My DNS Server/Provider>
 
    .DESCRIPTION
        Description for <My DNS Server/Provider>
 
    .PARAMETER RecordName
        The fully qualified name of the TXT record.
 
    .PARAMETER TxtValue
        The value of the TXT record.
 
    .PARAMETER AddrToolsSecret
        The secret associated with your challenges.addr.tools subdomain.
 
    .PARAMETER AddrToolsHost
        If self-hosting, domain name of your challenges.addr.tools equivalent (e.g. challenges.example.com)
 
    .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' 'txt-value'
 
        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.
    #>

}

############################
# Helper Functions
############################

# https://challenges.addr.tools/

function Get-AddrToolsCNAME {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory,Position=0)]
        [string[]]$Domain,
        [Parameter(Mandatory,Position=1)]
        [securestring]$AddrToolsSecret,
        [string]$AddrToolsHost='challenges.addr.tools'
    )

    $challengeSub = Get-AddrToolsSubdomain $AddrToolsSecret -AddrToolsHost $AddrToolsHost

    # Create a unique list of domains after stripping wildcards
    $Domain | Select-Object @{
        L='FQDN';  E={ '_acme-challenge.{0}' -f $_.TrimStart('*.') }
    },@{
        L='Target';E={ $challengeSub }
    } | Select-Object -Unique *
}

function Get-AddrToolsSubdomain {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory,Position=0)]
        [securestring]$AddrToolsSecret,
        [string]$AddrToolsHost='challenges.addr.tools'
    )

    if (-not $script:UseBasic) {
        $script:UseBasic = @{UseBasicParsing=$true}
    }

    # The subdomain for a give secret is the SHA-224 hash of the secret
    # prepended to the challenges FQDN. So by default:
    # <sha224>.challenges.addr.tools
    #
    # Until we have a local SHA-224 hashing implementation, you can get this
    # value by querying the endpoint with just the secret and no other arguments.

    $secPlain = [pscredential]::new('a',$AddrToolsSecret).GetNetworkCredential().Password

    $queryParams = @{
        Uri = 'https://{0}' -f $AddrToolsHost
        Method = 'POST'
        Body = @{
            secret = $secPlain
        }
        Verbose = $false
        ErrorAction = 'Stop'
    }
    try {
        Write-Debug "POST $($queryParams.Uri)"
        $resp = Invoke-RestMethod @queryParams @script:UseBasic
    } catch { throw }

    return $resp.Trim().TrimEnd('.')
}