Skip to content

Commit

Permalink
Add plugin for online.net (#559)
Browse files Browse the repository at this point in the history
  • Loading branch information
rmbolger authored Aug 3, 2024
1 parent 6fe18a6 commit 2a3e5ce
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 0 deletions.
304 changes: 304 additions & 0 deletions Posh-ACME/Plugins/OnlineNet.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
function Get-CurrentPluginType { 'dns-01' }

function Add-DnsTxt {
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$RecordName,
[Parameter(Mandatory,Position=1)]
[string]$TxtValue,
[Parameter(Mandatory,Position=2)]
[securestring]$ONToken,
[Parameter(ValueFromRemainingArguments)]
$ExtraParams
)

# get the plaintext version of the token
$ONTokenInsecure = [pscredential]::new('a',$ONToken).GetNetworkCredential().Password
$authHeader = @{Authorization="Bearer $ONTokenInsecure"}

# get the zone name for our record
$zoneName = Find-Zone $RecordName $authHeader
if ([String]::IsNullOrWhiteSpace($zoneName)) {
throw "Unable to find zone for $RecordName"
}
Write-Debug "Found zone $zoneName"

# grab the relative portion of the fqdn
$recShort = ($RecordName -ireplace [regex]::Escape($zoneName), [string]::Empty).TrimEnd('.')
if ($recShort -eq [string]::Empty) { $recShort = '@' }

$rec = Find-TxtRec $recShort $zoneName $TxtValue $authHeader

if ($rec) {
Write-Debug "Record $RecordName already contains $TxtValue. Nothing to do."
} else {
Write-Verbose "Adding a TXT record for $RecordName with value $TxtValue"

# build the change object
$newRec = @(
@{
changeType = 'ADD'
name = $recShort
type = 'TXT'
records = @(
@{
name = $recShort
type = 'TXT'
ttl = 300
data = "`"$TxtValue`""
}
)
}
)

# build the request
$queryParams = @{
Uri = 'https://api.online.net/api/v1/domain/{0}/version/active' -f $zoneName
Method = 'PATCH'
Body = ConvertTo-Json $newRec -Compress -Depth 5
Headers = $authHeader
ContentType = 'application/json'
Verbose = $false
ErrorAction = 'Stop'
}

# send the request
try {
Write-Debug "$($queryParams.Method) $($queryParams.Uri)`n$($queryParams.Body)"
Invoke-RestMethod @queryParams @script:UseBasic
} catch { throw }
}

<#
.SYNOPSIS
Add a DNS TXT record to online.net.
.DESCRIPTION
Add a DNS TXT record to online.net
.PARAMETER RecordName
The fully qualified name of the TXT record.
.PARAMETER TxtValue
The value of the TXT record.
.PARAMETER ONToken
The access API token for online.net
.PARAMETER ExtraParams
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports.
.EXAMPLE
$token = Read-Host "online.net Token" -AsSecureString
PS C:\>Add-DnsTxt '_acme-challenge.example.com' 'txt-value' $token
Adds a TXT record for the specified site with the specified value on Windows.
#>
}

function Remove-DnsTxt {
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$RecordName,
[Parameter(Mandatory,Position=1)]
[string]$TxtValue,
[Parameter(Mandatory,Position=2)]
[securestring]$ONToken,
[Parameter(ValueFromRemainingArguments)]
$ExtraParams
)

# get the plaintext version of the token
$ONTokenInsecure = [pscredential]::new('a',$ONToken).GetNetworkCredential().Password
$authHeader = @{Authorization="Bearer $ONTokenInsecure"}

# get the zone name for our record
$zoneName = Find-Zone $RecordName $authHeader
if ([String]::IsNullOrWhiteSpace($zoneName)) {
throw "Unable to find zone for $RecordName"
}
Write-Debug "Found zone $zoneName"

# grab the relative portion of the fqdn
$recShort = ($RecordName -ireplace [regex]::Escape($zoneName), [string]::Empty).TrimEnd('.')
if ($recShort -eq [string]::Empty) { $recShort = '@' }

$rec = Find-TxtRec $recShort $zoneName $TxtValue $authHeader

if ($rec) {
Write-Verbose "Removing TXT record for $RecordName with value $TxtValue"

# build the change object
$newRec = @(
@{
changeType = 'DELETE'
name = $recShort
type = 'TXT'
data = "`"$TxtValue`""
# records = @(
# @{
# name = $recShort
# type = 'TXT'
# ttl = 300
# data = "`"$TxtValue`""
# }
# )
}
)

# build the request
$queryParams = @{
Uri = 'https://api.online.net/api/v1/domain/{0}/version/active' -f $zoneName
Method = 'PATCH'
Body = ConvertTo-Json $newRec -Compress -Depth 5
Headers = $authHeader
ContentType = 'application/json'
Verbose = $false
ErrorAction = 'Stop'
}

# send the request
try {
Write-Debug "$($queryParams.Method) $($queryParams.Uri)`n$($queryParams.Body)"
Invoke-RestMethod @queryParams @script:UseBasic
} catch { throw }

} else {
Write-Debug "Record $RecordName with value $TxtValue doesn't exist. Nothing to do."
}

<#
.SYNOPSIS
Remove a DNS TXT record from online.net.
.DESCRIPTION
Remove a DNS TXT record from online.net.
.PARAMETER RecordName
The fully qualified name of the TXT record.
.PARAMETER TxtValue
The value of the TXT record.
.PARAMETER ONToken
The access API token for online.net.
.PARAMETER ExtraParams
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports.
.EXAMPLE
$token = Read-Host "online.net Token" -AsSecureString
PS C:\>Remove-DnsTxt '_acme-challenge.example.com' 'txt-value' $token
Removes a TXT record for the specified site with the specified value on Windows.
#>
}

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
############################

# API Docs
# https://console.online.net/en/api/

function Find-Zone {
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$RecordName,
[Parameter(Mandatory,Position=1)]
[hashtable]$AuthHeader
)

# setup a module variable to cache the record to zone mapping
# so it's quicker to find later
if (!$script:ONRecordZones) { $script:ONRecordZones = @{} }

# check for the record in the cache
if ($script:ONRecordZones.ContainsKey($RecordName)) {
return $script:ONRecordZones.$RecordName
}

# find the portion of the record that matches the zone name
$pieces = $RecordName.Split('.')
for ($i=0; $i -lt ($pieces.Count-1); $i++) {
$zoneTest = $pieces[$i..($pieces.Count-1)] -join '.'
Write-Debug "Checking $zoneTest"
try {
$queryParams = @{
Uri = 'https://api.online.net/api/v1/domain/{0}' -f $zoneTest
Method = 'GET'
Headers = $AuthHeader
Verbose = $false
ErrorAction = 'Stop'
}
Write-Debug "$($queryParams.Method) $($queryParams.Uri)"
# if the call succeeds, the zone exists, so we don't care about the actual response
$resp = Invoke-RestMethod @queryParams @script:UseBasic
Write-Debug "Response`n$($resp | ConvertTo-Json -Dep 10)"
$script:ONRecordZones.$RecordName = $zoneTest
return $zoneTest
} catch {
if (404 -ne $_.Exception.Response.StatusCode) { throw }
Write-Debug ($_.ToString())
}
}

return $null
}

function Find-TxtRec {
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$RecShort,
[Parameter(Mandatory,Position=1)]
[string]$ZoneName,
[Parameter(Mandatory,Position=2)]
[string]$TxtValue,
[Parameter(Mandatory,Position=3)]
[hashtable]$AuthHeader
)

# query the record data and return a matching TXT record if it exists
Write-Debug "Querying $ZoneName records"
$queryParams = @{
Uri = 'https://api.online.net/api/v1/domain/{0}/zone' -f $ZoneName
Method = 'GET'
Headers = $AuthHeader
Verbose = $false
ErrorAction = 'Stop'
}
try {
Write-Debug "GET $($queryParams.Uri)"
$recs = Invoke-RestMethod @queryParams @script:UseBasic
Write-Debug "$($recs.Count) records returned"
} catch { throw }

$rec = $recs | Where-Object {
$_.name -eq $RecShort -and
$_.data -eq "`"$TxtValue`""
}

return $rec
}
1 change: 1 addition & 0 deletions Posh-ACME/Private/Import-PluginDetail.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function Import-PluginDetail {
'NameCom' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'NameCom'}
'NameSilo' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'NameSilo'}
'NS1' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'NS1'}
'OnlineNet' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'OnlineNet'}
'OVH' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'OVH'}
'PointDNS' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'PointDNS'}
'Porkbun' = [pscustomobject]@{PSTypeName = 'PoshACME.PAPluginDetail'; ChallengeType = 'dns-01'; Path = ''; Name = 'Porkbun'}
Expand Down
20 changes: 20 additions & 0 deletions docs/Plugins/OnlineNet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
title: OnlineNet

# How To Use the OnlineNet DNS Plugin

This plugin works against the [Online.net](https://www.scaleway.com/en/domains-and-dns/) DNS provider which is now known as Scaleway. However, this plugin only works against the legacy online.net v1 API. It is assumed that you have already setup an account and purchased the domain you will be working with that can be managed from the legacy [console.online.net](https://console.online.net/) dashboard.

## Setup

Login to [API Access](https://console.online.net/en/api/access) and record your "private access token". You can also generate a new one at will and record that instead. But only the last generated token will work.

## Using the Plugin

Use your token value with the `ONToken` SecureString parameter.

```powershell
$pArgs = @{
ONToken = (Read-Host "Online.net Token" -AsSecureString)
}
New-PACertificate example.com -Plugin OnlineNet -PluginArgs $pArgs
```
1 change: 1 addition & 0 deletions docs/Plugins/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Manual | Manual Record Creation | | :white_check_mark:
Namecheap | [Namecheap FreeDNS](https://www.namecheap.com/domains/freedns/) | [Usage Guide](Namecheap.md) | :white_check_mark:
NameCom | [Name.com](https://www.name.com/) | [Usage Guide](NameCom.md) | :white_check_mark:
NS1 | [NS1 DNS](https://ns1.com) | [Usage Guide](NS1.md) | :white_check_mark:
OnlineNet | [Online.net/Scaleway](https://www.scaleway.com/en/domains-and-dns/) | [Usage Guide](OnlineNet.md) | :white_check_mark:
OVH | [OVH.com](https://www.ovh.com) | [Usage Guide](OVH.md) | :white_check_mark:
PointDNS | [PointDNS](https://pointhq.com/) | [Usage Guide](PointDNS.md) | :white_check_mark:
Porkbun | [Porkbun](https://porkbun.com/) | [Usage Guide](Porkbun.md) | :white_check_mark:
Expand Down

0 comments on commit 2a3e5ce

Please sign in to comment.