-
-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
336 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
function Get-CurrentPluginType { 'dns-01' } | ||
|
||
function Add-DnsTxt { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory,Position=0)] | ||
[string]$RecordName, | ||
[Parameter(Mandatory,Position=1)] | ||
[string]$TxtValue, | ||
[Parameter(Mandatory)] | ||
[pscredential]$WedosCredential, | ||
[Parameter(ValueFromRemainingArguments)] | ||
$ExtraParams | ||
) | ||
|
||
$zone = Find-Zone $RecordName $WedosCredential | ||
if (-not $zone) { | ||
throw "Unable to find zone for $RecordName in WEDOS" | ||
} | ||
Write-Debug "Found zone $zone" | ||
|
||
# setup a tracking variable for zones we need to "commit" | ||
if (-not $script:WedosZonesToSave) { $script:WedosZonesToSave = @() } | ||
|
||
if (-not (Find-TxtRec $RecordName $TxtValue $zone $WedosCredential)) { | ||
# empty string short names are ok for zone apex | ||
$recShort = ($RecordName -ireplace [regex]::Escape($zone), [string]::Empty).TrimEnd('.') | ||
$data = @{ | ||
domain = $zone | ||
name = $recShort | ||
type = 'TXT' | ||
rdata = $TxtValue | ||
ttl = 300 # minimum | ||
} | ||
Invoke-Wedos dns-row-add $WedosCredential -Data $data | ||
if ($zone -notin $script:WedosZonesToSave) { | ||
$script:WedosZonesToSave += $zone | ||
} | ||
} | ||
else { | ||
Write-Debug "Record $RecordName already contains $TxtValue. Nothing to do." | ||
} | ||
|
||
<# | ||
.SYNOPSIS | ||
Add a DNS TXT record to WEDOS | ||
.DESCRIPTION | ||
Add a DNS TXT record to WEDOS | ||
.PARAMETER RecordName | ||
The fully qualified name of the TXT record. | ||
.PARAMETER TxtValue | ||
The value of the TXT record. | ||
.PARAMETER WedosCredential | ||
The account username and API password. | ||
.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' -WedosCredential (Get-Credential) | ||
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)] | ||
[pscredential]$WedosCredential, | ||
[Parameter(ValueFromRemainingArguments)] | ||
$ExtraParams | ||
) | ||
|
||
$zone = Find-Zone $RecordName $WedosCredential | ||
if (-not $zone) { | ||
throw "Unable to find zone for $RecordName in WEDOS" | ||
} | ||
Write-Debug "Found zone $zone" | ||
|
||
# setup a tracking variable for zones we need to "commit" | ||
if (-not $script:WedosZonesToSave) { $script:WedosZonesToSave = @() } | ||
|
||
if (-not ($rec = Find-TxtRec $RecordName $TxtValue $zone $WedosCredential)) { | ||
Write-Debug "Record $RecordName with value $TxtValue doesn't exist. Nothing to do." | ||
} | ||
else { | ||
$data = @{ | ||
domain = $zone | ||
row_id = $rec.ID | ||
} | ||
Invoke-Wedos dns-row-delete $WedosCredential -Data $data | ||
if ($zone -notin $script:WedosZonesToSave) { | ||
$script:WedosZonesToSave += $zone | ||
} | ||
} | ||
|
||
<# | ||
.SYNOPSIS | ||
Remove a DNS TXT record from WEDOS | ||
.DESCRIPTION | ||
Remove a DNS TXT record from WEDOS | ||
.PARAMETER RecordName | ||
The fully qualified name of the TXT record. | ||
.PARAMETER TxtValue | ||
The value of the TXT record. | ||
.PARAMETER WedosCredential | ||
The account username and API password. | ||
.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' -WedosCredential (Get-Credential) | ||
Removes a TXT record for the specified site with the specified value. | ||
#> | ||
} | ||
|
||
function Save-DnsTxt { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory)] | ||
[pscredential]$WedosCredential, | ||
[Parameter(ValueFromRemainingArguments)] | ||
$ExtraParams | ||
) | ||
|
||
foreach ($zone in $script:WedosZonesToSave) { | ||
Write-Verbose "Applying changes for $zone zone" | ||
$data = @{ | ||
name = $zone | ||
} | ||
Invoke-Wedos dns-domain-commit $WedosCredential -Data $data | ||
} | ||
$script:WedosZonesToSave = @() | ||
|
||
<# | ||
.SYNOPSIS | ||
Commit changes to WEDOS zones. | ||
.DESCRIPTION | ||
Commit changes to WEDOS zones. | ||
.PARAMETER WedosCredential | ||
The account username and API password. | ||
.PARAMETER ExtraParams | ||
This parameter can be ignored and is only used to prevent errors when splatting with more parameters than this function supports. | ||
.EXAMPLE | ||
Save-DnsTxt -WedosCredential (Get-Credential) | ||
Commits changes to zones modified by Add-DnsTxt and Save-DnsTxt | ||
#> | ||
} | ||
|
||
############################ | ||
# Helper Functions | ||
############################ | ||
|
||
# https://kb.wedos.com/cs/wapi-api-rozhrani/zakladni-informace-wapi-api-rozhrani/wapi-zakladni-informace/ | ||
# https://kb.wedos.com/en/wapi-api-interface/wdns-en/wapi-wdns/ | ||
|
||
function Invoke-Wedos { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory,Position=0)] | ||
[string]$Command, | ||
[Parameter(Mandatory,Position=1)] | ||
[pscredential]$Credential, | ||
[hashtable]$Data, | ||
[int[]]$AltGoodCodes=@() | ||
) | ||
|
||
# The auth protocol for this API is rather...unique. | ||
|
||
# Get a SHA1 hash of the password | ||
$sha1 = [Security.Cryptography.SHA1CryptoServiceProvider]::new() | ||
$hashBytes = $sha1.ComputeHash([Text.Encoding]::UTF8.GetBytes($Credential.GetNetworkCredential().Password)) | ||
$pHash = [BitConverter]::ToString($hashBytes).Replace('-','').ToLower() | ||
|
||
# For some reason, the auth protocol requires the current 00-24 hour | ||
# with leading zeros specifically in the Europe/Prague time zone. | ||
$nowUtc = [DateTime]::UtcNow | ||
$hour = [TimeZoneInfo]::ConvertTimeFromUtc( | ||
$nowUtc, | ||
# Despite being "Standard" time, this will auto-convert | ||
# to "Summer" time when appropriate. | ||
[TimeZoneInfo]::FindSystemTimeZoneById('Central Europe Standard Time') | ||
).ToString('HH') | ||
|
||
# Concatenate the username, hashed password, and hour | ||
# and then SHA1 hash the whole thing | ||
$authRaw = '{0}{1}{2}' -f $Credential.Username,$pHash,$hour | ||
Write-Debug "authRaw = $authRaw" | ||
$hashBytes = $sha1.ComputeHash([Text.Encoding]::UTF8.GetBytes($authRaw)) | ||
$auth = [BitConverter]::ToString($hashBytes).Replace('-','').ToLower() | ||
|
||
# Build the request object | ||
$req = @{ | ||
request = @{ | ||
user = $Credential.UserName | ||
auth = $auth | ||
clTRID = "Posh-ACME $(New-Guid)" # client request ID | ||
command = $Command | ||
} | ||
} | ||
if ($Data) { | ||
$req.request.data = $Data | ||
} | ||
|
||
$queryParams = @{ | ||
Uri = 'https://api.wedos.com/wapi/json' | ||
Method = 'POST' | ||
# Send the JSON request as a value of "request" that is | ||
# application/x-www-form-urlencoded instead of just raw JSON | ||
Body = @{request=($req | ConvertTo-Json -Compress -Depth 10)} | ||
Verbose = $false | ||
ErrorAction = 'Stop' | ||
} | ||
Write-Debug "POST $($queryParams.Uri)`n$($req|ConvertTo-Json -Depth 10)" | ||
$resp = Invoke-RestMethod @queryParams @script:UseBasic | ||
Write-Debug "Response:`n$($resp|ConvertTo-Json -Depth 10)" | ||
|
||
if ($resp.response.code -ne 1000 -and $resp.response.code -notin $AltGoodCodes) { | ||
"WEDOS API Error $($resp.response.code): $($resp.response.result)" | ||
} | ||
return $resp.response.data | ||
} | ||
|
||
function Find-Zone { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory,Position=0)] | ||
[string]$RecordName, | ||
[Parameter(Mandatory,Position=1)] | ||
[pscredential]$Credential | ||
) | ||
|
||
# setup a module variable to cache the record to zone mapping | ||
# so it's quicker to find later and uses fewer API calls | ||
if (!$script:WedosRecordZones) { $script:WedosRecordZones = @{} } | ||
|
||
# check for the record in the cache | ||
if ($script:WedosRecordZones.ContainsKey($RecordName)) { | ||
return $script:WedosRecordZones.$RecordName | ||
} | ||
|
||
# Get all of the domains on the account | ||
$zones = Invoke-Wedos dns-domains-list $Credential | Select-Object -Expand domain | ||
if (-not $zones) { | ||
Write-Warning "No WEDOS hosted domains found." | ||
return | ||
} | ||
|
||
# find the zone for the closest/deepest sub-zone that would contain the record. | ||
$pieces = $RecordName.Split('.') | ||
for ($i=0; $i -lt ($pieces.Count-1); $i++) { | ||
$zoneTest = $pieces[$i..($pieces.Count-1)] -join '.' | ||
Write-Debug "Checking $zoneTest" | ||
|
||
$match = $zones | Where-Object { $zoneTest -eq $_.name } | Select-Object -First 1 | ||
if ($match) { | ||
$script:WedosRecordZones.$RecordName = $zoneTest | ||
return $zoneTest | ||
} | ||
} | ||
} | ||
|
||
function Find-TxtRec { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory,Position=0)] | ||
[string]$RecordName, | ||
[Parameter(Mandatory,Position=1)] | ||
[string]$TxtValue, | ||
[Parameter(Mandatory,Position=2)] | ||
[string]$Zone, | ||
[Parameter(Mandatory,Position=3)] | ||
[pscredential]$Credential | ||
) | ||
|
||
# Get all of the records in the zone | ||
$recs = Invoke-Wedos dns-rows-list $Credential -Data @{domain=$Zone} | Select-Object -Expand row | ||
if (-not $recs) { | ||
Write-Warning "No WEDOS records found." | ||
return | ||
} | ||
|
||
return $recs | Where-Object { | ||
$RecordName -eq "$($_.name).$Zone".Trim('.') -and | ||
$_.rdtype -eq 'TXT' -and | ||
$_.rdata -eq $TxtValue | ||
} | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
title: WEDOS | ||
|
||
# How To Use the WEDOS DNS Plugin | ||
|
||
This plugin works against the [WEDOS](https://www.wedos.com/zone/) DNS provider. It is assumed that you have already setup an account and added or registered the DNS domain(s) you will be working against. | ||
|
||
## Setup | ||
|
||
The WAPI (Web API) needs to be explicitly enabled on your account before you can use it. If you haven't already, follow the [instructions here](https://kb.wedos.com/en/wapi-api-interface/wapi-activation-and-settings/). | ||
|
||
First it will have you agree to the ToS. Then double check that the IP address you will be connecting from is in the `Allowed IP addresses` field and the preferred protocol is `JSON`. You'll also need to set a password specifically for API access (which should be different than your primary account password). | ||
|
||
## Using the Plugin | ||
|
||
You will need to provide your account username/email and API password as a PSCredential object to the `WedosCredential` plugin parameter. | ||
|
||
!!! warning | ||
WEDOS seems to have an unusually long propagation time between when your DNS changes are committed and when they are reflected on their authoritative nameservers. The GUI warns that changes could take up to 60 minutes. But testing has show the average time is around 4-8 minutes. Be sure to use the `-DnsSleep` parameter with an appropriately long timeout | ||
to avoid validation failures. | ||
|
||
```powershell | ||
$pArgs = @{ | ||
WedosCredential = (Get-Credential) | ||
} | ||
New-PACertificate example.com -Plugin WEDOS -PluginArgs $pArgs -DnsSleep 600 | ||
``` |
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