Plugins/CoreNetworks.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)] [pscredential]$CoreNetworksCred, [string]$CoreNetworksApiRoot = 'https://beta.api.core-networks.de', [Parameter(ValueFromRemainingArguments)] $ExtraParams ) ### Authentication at the API via authentication token, which must be sent in the headers of every request. $headers = @{ Authorization="Bearer $(Get-CoreNetworksAuthToken $CoreNetworksApiRoot $CoreNetworksCred)" } ### Search und find the dns zone of the (sub)domain (for example: example.com). $zoneName = $(Find-CoreNetworksDnsZones $CoreNetworksApiRoot $headers $RecordName) Write-Debug $zoneName ### Grab the relative portion of the Fully Qualified Domain Name (FQDN) $DnsTxtName = ($RecordName -ireplace [regex]::Escape($zoneName), [string]::Empty).TrimEnd('.') Write-Debug $DnsTxtName # build the add record query # API will ignore if the record already exists $queryParams = @{ Uri = "$CoreNetworksApiRoot/dnszones/$zoneName/records/" Method = 'POST' Body = @{ name = $DnsTxtName ttl = 60 type = 'TXT' data = "`"$TxtValue`"" } | ConvertTo-Json Headers = $headers ContentType = 'application/json' Verbose = $false ErrorAction = 'Stop' } ### Send a POST request including bearer authentication. try { Write-Debug "POST $($queryParams.Uri)`n$($queryParams.Body)" Invoke-RestMethod @queryParams @script:UseBasic | Out-Null } catch { Write-Debug $_ throw } # Add the zone name to a script variable so the Save function can commit # all changes at once when it's called. if (-not $script:CoreNetworksZones) { $script:CoreNetworksZones = @() } $script:CoreNetworksZones += $zoneName <# .SYNOPSIS Add a DNS TXT record to CoreNetworks. .DESCRIPTION Add a DNS TXT record to CoreNetworks. .PARAMETER RecordName The fully qualified name of the TXT record. .PARAMETER TxtValue The value of the TXT record. .PARAMETER CoreNetworksCred The API username and password required to authenticate. .PARAMETER CoreNetworksApiRoot The root URL of the API. Defaults to https://beta.api.core-networks.de .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' -CoreNetworksCred (Get-Credential) Adds a TXT record using credentials and ignores certificate validation. #> } function Remove-DnsTxt { [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [string]$RecordName, [Parameter(Mandatory, Position = 1)] [string]$TxtValue, [Parameter(Mandatory)] [pscredential]$CoreNetworksCred, [string]$CoreNetworksApiRoot = 'https://beta.api.core-networks.de', [Parameter(ValueFromRemainingArguments)] $ExtraParams ) ### Authentication at the API via authentication token, which must be sent in the headers of every request. $headers = @{ Authorization="Bearer $(Get-CoreNetworksAuthToken $CoreNetworksApiRoot $CoreNetworksCred)" } ### Search und find the dns zone of the (sub)domain (for example: example.com). $zoneName = $(Find-CoreNetworksDnsZones $CoreNetworksApiRoot $headers $RecordName) Write-Debug $zoneName ### Grab the relative portion of the Fully Qualified Domain Name (FQDN) $DnsTxtName = ($RecordName -ireplace [regex]::Escape($zoneName), [string]::Empty).TrimEnd('.') Write-Debug $DnsTxtName # build the delete record query # API will ignore if the record we're deleting doesn't exist $queryParams = @{ Uri = "$CoreNetworksApiRoot/dnszones/$zoneName/records/delete" Method = 'POST' Body = @{ name = $DnsTxtName data = "`"$TxtValue`"" } | ConvertTo-Json Headers = $headers ContentType = 'application/json' Verbose = $false ErrorAction = 'Stop' } ### Send a POST request including bearer authentication. try { Write-Debug "POST $($queryParams.Uri)`n$($queryParams.Body)" Invoke-RestMethod @queryParams @script:UseBasic | Out-Null } catch { Write-Debug $_ throw } # Add the zone name to a script variable so the Save function can commit # all changes at once when it's called. if (-not $script:CoreNetworksZones) { $script:CoreNetworksZones = @() } $script:CoreNetworksZones += $zoneName <# .SYNOPSIS Add a DNS TXT record to CoreNetworks. .DESCRIPTION Add a DNS TXT record to CoreNetworks. .PARAMETER RecordName The fully qualified name of the TXT record. .PARAMETER TxtValue The value of the TXT record. .PARAMETER CoreNetworksCred The API username and password required to authenticate. .PARAMETER CoreNetworksApiRoot The root URL of the API. Defaults to https://beta.api.core-networks.de .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' -CoreNetworksCred (Get-Credential) Removes a TXT record for the specified site with the specified value. #> } function Save-DnsTxt { [CmdletBinding()] param( [Parameter(Mandatory)] [pscredential]$CoreNetworksCred, [string]$CoreNetworksApiRoot = 'https://beta.api.core-networks.de', [Parameter(ValueFromRemainingArguments)] $ExtraParams ) ### Our current backend for the name server is not suitable for the high-frequency processing of DNS records. So that you can make ### major changes to DNS zones quickly without having to wait for the name server, changes to the DNS records are not transmitted ### to the name servers immediately. Instead, when you are done changing DNS records, you must commit the zone. # return early if there's nothing to commit if (-not $script:CoreNetworksZones) { return } # get a fresh auth token $headers = @{ Authorization="Bearer $(Get-CoreNetworksAuthToken $CoreNetworksApiRoot $CoreNetworksCred)" } # commit each unique zone $script:CoreNetworksZones | Sort-Object -Unique | ForEach-Object { $queryParams = @{ Uri = "$CoreNetworksApiRoot/dnszones/$_/records/commit" Method = 'POST' Headers = $headers ContentType = 'application/json' Verbose = $false ErrorAction = 'Stop' } ### Send a POST request including bearer authentication. try { Write-Verbose "Committing changes for $_" Write-Debug "POST $($queryParams.Uri)" Invoke-RestMethod @queryParams @script:UseBasic | Out-Null } catch { Write-Debug $_ throw } } if ($script:CoreNetworksZones) { Remove-Variable CoreNetworksZones -Scope Script } <# .SYNOPSIS Commit changes made to Core Networks zones .DESCRIPTION This provider does not require calling this function to commit changes to DNS records. .PARAMETER CoreNetworksCred The API username and password required to authenticate. .PARAMETER CoreNetworksApiRoot The root URL of the API. Defaults to https://beta.api.core-networks.de .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 -CoreNetworksCred (Get-Credential) Commits changes to zones modified by Add-DnsTxt and Remove-DnsTxt. #> } ############################ # Helper Functions ############################ # API Docs # https://beta.api.core-networks.de/doc/ ### To get a token, you need an API user account. You can set this up in the API user account management in our web interface. function Get-CoreNetworksAuthToken { [CmdletBinding()] param( [Parameter(Mandatory, Position=0)] [string]$ApiRootUrl, [Parameter(Mandatory, Position=1)] [pscredential]$Cred ) $passPlain = $Cred.GetNetworkCredential().Password # Request a new bearer token using the credentials. $queryParams = @{ Uri = "$ApiRootUrl/auth/token" Method = 'POST' Body = @{ login = $Cred.UserName password = $passPlain } | ConvertTo-Json ContentType = 'application/json' Verbose = $false ErrorAction = 'Stop' } try { # sanitize the body so we don't log the plaintext password Write-Debug "POST $($queryParams.Uri)`n$($queryParams.Body.Replace($passPlain,'XXXXXXXX'))" $data = Invoke-RestMethod @queryParams @script:UseBasic return $data.token } catch { Write-Debug $_ throw } } ### With the following function you get a list of all DNS zones that you currently have. function Find-CoreNetworksDnsZones { [CmdletBinding()] param( [Parameter(Mandatory, Position=0)] [System.Object]$ApiRootUrl, [Parameter(Mandatory, Position=1)] [System.Object]$Headers, [Parameter(Mandatory, Position=2)] [string]$RecordName ) ### Send a POST request including bearer authentication. try { $queryParams = @{ Uri = "$ApiRootUrl/dnszones/" Headers = $Headers Verbose = $false ErrorAction = 'Stop' } Write-Debug "GET $($queryParams.Uri)" $data = Invoke-RestMethod @queryParams @script:UseBasic foreach ($e in $data.name) { if ($RecordName -match $e ) { return $e } } } catch { Write-Debug $_ throw } } |