-
-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added AddrTools plugin and guide (#574)
- Loading branch information
Showing
4 changed files
with
271 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,217 @@ | ||
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('.') | ||
} |
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,52 @@ | ||
title: AddrTools | ||
|
||
# How To Use the AddrTools DNS Plugin | ||
|
||
This plugin works against [challenges.addr.tools](https://challenges.addr.tools/) which is a specialized provider purpose built for validating dns-01 challenges using CNAME aliases. It is part of the larger [addr.tools](https://www.addr.tools/) open source project which means you can self-host your own instance. But the default configuration works against the author's public instance. | ||
|
||
## Setup | ||
|
||
It may help to read the [Using DNS Challenge Aliases](../Guides/Using-DNS-Challenge-Aliases.md) guide to better understand how CNAME records work with ACME challenges. Most importantly, there will be a one-time CNAME record creation for each name in the certificate you are requesting. | ||
|
||
There is a helper function in the plugin to help determine which CNAME records to create. It uses the same parameters that the AddrTools plugin uses. So use the following code to create an appropriate `$pArgs` variable and a `$domains` variable that contains the list of domains in your certificate. | ||
|
||
```powershell | ||
$pArgs = @{ | ||
AddrToolsSecret = Read-Host -Prompt "Enter Secret" -AsSecureString | ||
AddrToolsHost = 'challenges.addr.tools' # optional unless self-hosting | ||
} | ||
$domains = 'example.com','www.example.com' | ||
``` | ||
|
||
Now run the following to load and run the helper function that will tell you what CNAME records to create. | ||
|
||
```powershell | ||
Import-Module Posh-ACME | ||
. (Join-Path (Get-Module Posh-ACME).ModuleBase "Plugins\AddrTools.ps1") | ||
Get-AddrToolsCNAME $domains @pArgs | ||
``` | ||
|
||
The output will look similar to this depending on how many unique domains you have: | ||
|
||
``` | ||
FQDN Target | ||
---- ------ | ||
_acme-challenge.example.com 7870508034f01f4a28d86812fa7bd10a03cb7e7e6ddda0ddb95ff771.challenges.addr.tools | ||
_acme-challenge.www.example.com 7870508034f01f4a28d86812fa7bd10a03cb7e7e6ddda0ddb95ff771.challenges.addr.tools | ||
``` | ||
|
||
## Using the Plugin | ||
|
||
Once all necessary CNAME records are created, you can use the same `$pArgs` value from setup with the plugin. `AddrToolsSecret` is always required and `AddrToolsHost` is only required if you're self-hosting your own instance at a different domain. | ||
|
||
You'll also need to use the `-DnsAlias` parameter from New-PACertificate with the Target value from the CNAME records. | ||
|
||
```powershell | ||
# set this to the CNAME Target value from setup | ||
$target = 'xxxxxxxxxxxxxxxxxx.challenges.addr.tools' | ||
$pArgs = @{ | ||
AddrToolsSecret = (Read-Host 'Access Token' -AsSecureString) | ||
} | ||
New-PACertificate example.com -Plugin AddrTools -PluginArgs $pArgs -DnsAlias $target | ||
``` |
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