forked from TrueCloudLab/lego
Add DNS provider for all-inkl (#1444)
This commit is contained in:
parent
2a194d6ab9
commit
43779d7533
22 changed files with 1608 additions and 24 deletions
46
README.md
46
README.md
|
@ -46,29 +46,29 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
|
|||
|
||||
| | | | |
|
||||
|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------|
|
||||
| [Akamai EdgeDNS](https://go-acme.github.io/lego/dns/edgedns/) | [Alibaba Cloud DNS](https://go-acme.github.io/lego/dns/alidns/) | [Amazon Lightsail](https://go-acme.github.io/lego/dns/lightsail/) | [Amazon Route 53](https://go-acme.github.io/lego/dns/route53/) |
|
||||
| [ArvanCloud](https://go-acme.github.io/lego/dns/arvancloud/) | [Aurora DNS](https://go-acme.github.io/lego/dns/auroradns/) | [Autodns](https://go-acme.github.io/lego/dns/autodns/) | [Azure](https://go-acme.github.io/lego/dns/azure/) |
|
||||
| [Bindman](https://go-acme.github.io/lego/dns/bindman/) | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/) | [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/) | [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/) |
|
||||
| [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/) | [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/) | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/) | [ConoHa](https://go-acme.github.io/lego/dns/conoha/) |
|
||||
| [Constellix](https://go-acme.github.io/lego/dns/constellix/) | [deSEC.io](https://go-acme.github.io/lego/dns/desec/) | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) | [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/) |
|
||||
| [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/) | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/) | [DNSPod](https://go-acme.github.io/lego/dns/dnspod/) | [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/) |
|
||||
| [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/) | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/) | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/) | [Dyn](https://go-acme.github.io/lego/dns/dyn/) |
|
||||
| [Dynu](https://go-acme.github.io/lego/dns/dynu/) | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/) | [Exoscale](https://go-acme.github.io/lego/dns/exoscale/) | [External program](https://go-acme.github.io/lego/dns/exec/) |
|
||||
| [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/) | [Gandi](https://go-acme.github.io/lego/dns/gandi/) | [Glesys](https://go-acme.github.io/lego/dns/glesys/) | [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/) |
|
||||
| [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/) | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/) | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/) | [HTTP request](https://go-acme.github.io/lego/dns/httpreq/) |
|
||||
| [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/) | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/) | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/) | [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/) |
|
||||
| [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/) | [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/) | [INWX](https://go-acme.github.io/lego/dns/inwx/) | [Ionos](https://go-acme.github.io/lego/dns/ionos/) |
|
||||
| [Joker](https://go-acme.github.io/lego/dns/joker/) | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/) | [Linode (v4)](https://go-acme.github.io/lego/dns/linode/) | [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/) |
|
||||
| [Loopia](https://go-acme.github.io/lego/dns/loopia/) | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/) | [Manual](https://go-acme.github.io/lego/dns/manual/) | [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/) |
|
||||
| [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/) | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/) | [Namecheap](https://go-acme.github.io/lego/dns/namecheap/) | [Namesilo](https://go-acme.github.io/lego/dns/namesilo/) |
|
||||
| [Netcup](https://go-acme.github.io/lego/dns/netcup/) | [Netlify](https://go-acme.github.io/lego/dns/netlify/) | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/) | [Njalla](https://go-acme.github.io/lego/dns/njalla/) |
|
||||
| [NS1](https://go-acme.github.io/lego/dns/ns1/) | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/) | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/) | [OVH](https://go-acme.github.io/lego/dns/ovh/) |
|
||||
| [Porkbun](https://go-acme.github.io/lego/dns/porkbun/) | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) | [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) | [reg.ru](https://go-acme.github.io/lego/dns/regru/) |
|
||||
| [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/) | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) | [Scaleway](https://go-acme.github.io/lego/dns/scaleway/) |
|
||||
| [Selectel](https://go-acme.github.io/lego/dns/selectel/) | [Servercow](https://go-acme.github.io/lego/dns/servercow/) | [Simply.com](https://go-acme.github.io/lego/dns/simply/) | [Sonic](https://go-acme.github.io/lego/dns/sonic/) |
|
||||
| [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) | [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/) |
|
||||
| [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/) | [Vscale](https://go-acme.github.io/lego/dns/vscale/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) | [WEDOS](https://go-acme.github.io/lego/dns/wedos/) |
|
||||
| [Yandex](https://go-acme.github.io/lego/dns/yandex/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) | [Zonomi](https://go-acme.github.io/lego/dns/zonomi/) | |
|
||||
| [Akamai EdgeDNS](https://go-acme.github.io/lego/dns/edgedns/) | [Alibaba Cloud DNS](https://go-acme.github.io/lego/dns/alidns/) | [all-inkl](https://go-acme.github.io/lego/dns/allinkl/) | [Amazon Lightsail](https://go-acme.github.io/lego/dns/lightsail/) |
|
||||
| [Amazon Route 53](https://go-acme.github.io/lego/dns/route53/) | [ArvanCloud](https://go-acme.github.io/lego/dns/arvancloud/) | [Aurora DNS](https://go-acme.github.io/lego/dns/auroradns/) | [Autodns](https://go-acme.github.io/lego/dns/autodns/) |
|
||||
| [Azure](https://go-acme.github.io/lego/dns/azure/) | [Bindman](https://go-acme.github.io/lego/dns/bindman/) | [Bluecat](https://go-acme.github.io/lego/dns/bluecat/) | [Checkdomain](https://go-acme.github.io/lego/dns/checkdomain/) |
|
||||
| [CloudDNS](https://go-acme.github.io/lego/dns/clouddns/) | [Cloudflare](https://go-acme.github.io/lego/dns/cloudflare/) | [ClouDNS](https://go-acme.github.io/lego/dns/cloudns/) | [CloudXNS](https://go-acme.github.io/lego/dns/cloudxns/) |
|
||||
| [ConoHa](https://go-acme.github.io/lego/dns/conoha/) | [Constellix](https://go-acme.github.io/lego/dns/constellix/) | [deSEC.io](https://go-acme.github.io/lego/dns/desec/) | [Designate DNSaaS for Openstack](https://go-acme.github.io/lego/dns/designate/) |
|
||||
| [Digital Ocean](https://go-acme.github.io/lego/dns/digitalocean/) | [DNS Made Easy](https://go-acme.github.io/lego/dns/dnsmadeeasy/) | [DNSimple](https://go-acme.github.io/lego/dns/dnsimple/) | [DNSPod](https://go-acme.github.io/lego/dns/dnspod/) |
|
||||
| [Domain Offensive (do.de)](https://go-acme.github.io/lego/dns/dode/) | [Domeneshop](https://go-acme.github.io/lego/dns/domeneshop/) | [DreamHost](https://go-acme.github.io/lego/dns/dreamhost/) | [Duck DNS](https://go-acme.github.io/lego/dns/duckdns/) |
|
||||
| [Dyn](https://go-acme.github.io/lego/dns/dyn/) | [Dynu](https://go-acme.github.io/lego/dns/dynu/) | [EasyDNS](https://go-acme.github.io/lego/dns/easydns/) | [Exoscale](https://go-acme.github.io/lego/dns/exoscale/) |
|
||||
| [External program](https://go-acme.github.io/lego/dns/exec/) | [Gandi Live DNS (v5)](https://go-acme.github.io/lego/dns/gandiv5/) | [Gandi](https://go-acme.github.io/lego/dns/gandi/) | [Glesys](https://go-acme.github.io/lego/dns/glesys/) |
|
||||
| [Go Daddy](https://go-acme.github.io/lego/dns/godaddy/) | [Google Cloud](https://go-acme.github.io/lego/dns/gcloud/) | [Hetzner](https://go-acme.github.io/lego/dns/hetzner/) | [Hosting.de](https://go-acme.github.io/lego/dns/hostingde/) |
|
||||
| [HTTP request](https://go-acme.github.io/lego/dns/httpreq/) | [Hurricane Electric DNS](https://go-acme.github.io/lego/dns/hurricane/) | [HyperOne](https://go-acme.github.io/lego/dns/hyperone/) | [Infoblox](https://go-acme.github.io/lego/dns/infoblox/) |
|
||||
| [Infomaniak](https://go-acme.github.io/lego/dns/infomaniak/) | [Internet Initiative Japan](https://go-acme.github.io/lego/dns/iij/) | [Internet.bs](https://go-acme.github.io/lego/dns/internetbs/) | [INWX](https://go-acme.github.io/lego/dns/inwx/) |
|
||||
| [Ionos](https://go-acme.github.io/lego/dns/ionos/) | [Joker](https://go-acme.github.io/lego/dns/joker/) | [Joohoi's ACME-DNS](https://go-acme.github.io/lego/dns/acme-dns/) | [Linode (v4)](https://go-acme.github.io/lego/dns/linode/) |
|
||||
| [Liquid Web](https://go-acme.github.io/lego/dns/liquidweb/) | [Loopia](https://go-acme.github.io/lego/dns/loopia/) | [LuaDNS](https://go-acme.github.io/lego/dns/luadns/) | [Manual](https://go-acme.github.io/lego/dns/manual/) |
|
||||
| [MyDNS.jp](https://go-acme.github.io/lego/dns/mydnsjp/) | [MythicBeasts](https://go-acme.github.io/lego/dns/mythicbeasts/) | [Name.com](https://go-acme.github.io/lego/dns/namedotcom/) | [Namecheap](https://go-acme.github.io/lego/dns/namecheap/) |
|
||||
| [Namesilo](https://go-acme.github.io/lego/dns/namesilo/) | [Netcup](https://go-acme.github.io/lego/dns/netcup/) | [Netlify](https://go-acme.github.io/lego/dns/netlify/) | [NIFCloud](https://go-acme.github.io/lego/dns/nifcloud/) |
|
||||
| [Njalla](https://go-acme.github.io/lego/dns/njalla/) | [NS1](https://go-acme.github.io/lego/dns/ns1/) | [Open Telekom Cloud](https://go-acme.github.io/lego/dns/otc/) | [Oracle Cloud](https://go-acme.github.io/lego/dns/oraclecloud/) |
|
||||
| [OVH](https://go-acme.github.io/lego/dns/ovh/) | [Porkbun](https://go-acme.github.io/lego/dns/porkbun/) | [PowerDNS](https://go-acme.github.io/lego/dns/pdns/) | [Rackspace](https://go-acme.github.io/lego/dns/rackspace/) |
|
||||
| [reg.ru](https://go-acme.github.io/lego/dns/regru/) | [RFC2136](https://go-acme.github.io/lego/dns/rfc2136/) | [RimuHosting](https://go-acme.github.io/lego/dns/rimuhosting/) | [Sakura Cloud](https://go-acme.github.io/lego/dns/sakuracloud/) |
|
||||
| [Scaleway](https://go-acme.github.io/lego/dns/scaleway/) | [Selectel](https://go-acme.github.io/lego/dns/selectel/) | [Servercow](https://go-acme.github.io/lego/dns/servercow/) | [Simply.com](https://go-acme.github.io/lego/dns/simply/) |
|
||||
| [Sonic](https://go-acme.github.io/lego/dns/sonic/) | [Stackpath](https://go-acme.github.io/lego/dns/stackpath/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) | [VegaDNS](https://go-acme.github.io/lego/dns/vegadns/) |
|
||||
| [Versio.[nl/eu/uk]](https://go-acme.github.io/lego/dns/versio/) | [VinylDNS](https://go-acme.github.io/lego/dns/vinyldns/) | [Vscale](https://go-acme.github.io/lego/dns/vscale/) | [Vultr](https://go-acme.github.io/lego/dns/vultr/) |
|
||||
| [WEDOS](https://go-acme.github.io/lego/dns/wedos/) | [Yandex](https://go-acme.github.io/lego/dns/yandex/) | [Zone.ee](https://go-acme.github.io/lego/dns/zoneee/) | [Zonomi](https://go-acme.github.io/lego/dns/zonomi/) |
|
||||
|
||||
<!-- END DNS PROVIDERS LIST -->
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ func allDNSCodes() string {
|
|||
"manual",
|
||||
"acme-dns",
|
||||
"alidns",
|
||||
"allinkl",
|
||||
"arvancloud",
|
||||
"auroradns",
|
||||
"autodns",
|
||||
|
@ -150,6 +151,26 @@ func displayDNSHelp(name string) error {
|
|||
ew.writeln()
|
||||
ew.writeln(`More information: https://go-acme.github.io/lego/dns/alidns`)
|
||||
|
||||
case "allinkl":
|
||||
// generated from: providers/dns/allinkl/allinkl.toml
|
||||
ew.writeln(`Configuration for all-inkl.`)
|
||||
ew.writeln(`Code: 'allinkl'`)
|
||||
ew.writeln(`Since: 'v4.5.0'`)
|
||||
ew.writeln()
|
||||
|
||||
ew.writeln(`Credentials:`)
|
||||
ew.writeln(` - "ALL_INKL_API_KEY": API login`)
|
||||
ew.writeln(` - "ALL_INKL_PASSWORD": API password`)
|
||||
ew.writeln()
|
||||
|
||||
ew.writeln(`Additional Configuration:`)
|
||||
ew.writeln(` - "ALL_INKL_HTTP_TIMEOUT": API request timeout`)
|
||||
ew.writeln(` - "ALL_INKL_POLLING_INTERVAL": Time between DNS propagation check`)
|
||||
ew.writeln(` - "ALL_INKL_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
|
||||
|
||||
ew.writeln()
|
||||
ew.writeln(`More information: https://go-acme.github.io/lego/dns/allinkl`)
|
||||
|
||||
case "arvancloud":
|
||||
// generated from: providers/dns/arvancloud/arvancloud.toml
|
||||
ew.writeln(`Configuration for ArvanCloud.`)
|
||||
|
|
63
docs/content/dns/zz_gen_allinkl.md
Normal file
63
docs/content/dns/zz_gen_allinkl.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: "all-inkl"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
slug: allinkl
|
||||
---
|
||||
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
<!-- providers/dns/allinkl/allinkl.toml -->
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
|
||||
Since: v4.5.0
|
||||
|
||||
Configuration for [all-inkl](https://all-inkl.com).
|
||||
|
||||
|
||||
<!--more-->
|
||||
|
||||
- Code: `allinkl`
|
||||
|
||||
Here is an example bash command using the all-inkl provider:
|
||||
|
||||
```bash
|
||||
ALL_INKL_LOGIN=xxxxxxxxxxxxxxxxxxxxxxxxxx \
|
||||
ALL_INKL_PASSWORD=yyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
lego --email myemail@example.com --dns allinkl --domains my.example.org run
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Credentials
|
||||
|
||||
| Environment Variable Name | Description |
|
||||
|-----------------------|-------------|
|
||||
| `ALL_INKL_API_KEY` | API login |
|
||||
| `ALL_INKL_PASSWORD` | API password |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
More information [here](/lego/dns/#configuration-and-credentials).
|
||||
|
||||
|
||||
## Additional Configuration
|
||||
|
||||
| Environment Variable Name | Description |
|
||||
|--------------------------------|-------------|
|
||||
| `ALL_INKL_HTTP_TIMEOUT` | API request timeout |
|
||||
| `ALL_INKL_POLLING_INTERVAL` | Time between DNS propagation check |
|
||||
| `ALL_INKL_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
|
||||
|
||||
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
|
||||
More information [here](/lego/dns/#configuration-and-credentials).
|
||||
|
||||
|
||||
|
||||
|
||||
## More information
|
||||
|
||||
- [API documentation](https://kasapi.kasserver.com/dokumentation/phpdoc/index.html)
|
||||
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
||||
<!-- providers/dns/allinkl/allinkl.toml -->
|
||||
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
|
1
go.mod
1
go.mod
|
@ -31,6 +31,7 @@ require (
|
|||
github.com/linode/linodego v0.25.3
|
||||
github.com/liquidweb/liquidweb-go v1.6.3
|
||||
github.com/miekg/dns v1.1.40
|
||||
github.com/mitchellh/mapstructure v1.4.1
|
||||
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04
|
||||
github.com/nrdcg/auroradns v1.0.1
|
||||
github.com/nrdcg/desec v0.5.0
|
||||
|
|
3
go.sum
3
go.sum
|
@ -324,8 +324,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
|
|||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
161
providers/dns/allinkl/allinkl.go
Normal file
161
providers/dns/allinkl/allinkl.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
// Package allinkl implements a DNS provider for solving the DNS-01 challenge using all-inkl.
|
||||
package allinkl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/go-acme/lego/v4/providers/dns/allinkl/internal"
|
||||
)
|
||||
|
||||
// Environment variables names.
|
||||
const (
|
||||
envNamespace = "ALL_INKL_"
|
||||
|
||||
EnvLogin = envNamespace + "LOGIN"
|
||||
EnvPassword = envNamespace + "PASSWORD"
|
||||
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
)
|
||||
|
||||
// Config is used to configure the creation of the DNSProvider.
|
||||
type Config struct {
|
||||
Login string
|
||||
Password string
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewDefaultConfig returns a default configuration for the DNSProvider.
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// DNSProvider implements the challenge.Provider interface.
|
||||
type DNSProvider struct {
|
||||
config *Config
|
||||
client *internal.Client
|
||||
|
||||
recordIDs map[string]string
|
||||
recordIDsMu sync.Mutex
|
||||
}
|
||||
|
||||
// NewDNSProvider returns a DNSProvider instance configured for all-inkl.
|
||||
// Credentials must be passed in the environment variable: ALL_INKL_API_KEY, ALL_INKL_PASSWORD.
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvLogin, EnvPassword)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("allinkl: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.Login = values[EnvLogin]
|
||||
config.Password = values[EnvPassword]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
// NewDNSProviderConfig return a DNSProvider instance configured for all-inkl.
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("allinkl: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
if config.Login == "" || config.Password == "" {
|
||||
return nil, errors.New("allinkl: missing credentials")
|
||||
}
|
||||
|
||||
client := internal.NewClient(config.Login, config.Password)
|
||||
|
||||
if config.HTTPClient != nil {
|
||||
client.HTTPClient = config.HTTPClient
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
config: config,
|
||||
client: client,
|
||||
recordIDs: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||
// Adjusting here to cope with spikes in propagation times.
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters.
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
authZone, err := dns01.FindZoneByFqdn(fqdn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allinkl: could not determine zone for domain %q: %w", domain, err)
|
||||
}
|
||||
|
||||
credential, err := d.client.Authentication(60, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allinkl: %w", err)
|
||||
}
|
||||
|
||||
subDomain := dns01.UnFqdn(strings.TrimSuffix(fqdn, authZone))
|
||||
|
||||
record := internal.DNSRequest{
|
||||
ZoneHost: authZone,
|
||||
RecordType: "TXT",
|
||||
RecordName: subDomain,
|
||||
RecordData: value,
|
||||
}
|
||||
|
||||
recordID, err := d.client.AddDNSSettings(credential, record)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allinkl: %w", err)
|
||||
}
|
||||
|
||||
d.recordIDsMu.Lock()
|
||||
d.recordIDs[token] = recordID
|
||||
d.recordIDsMu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters.
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||
|
||||
credential, err := d.client.Authentication(60, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allinkl: %w", err)
|
||||
}
|
||||
|
||||
// gets the record's unique ID from when we created it
|
||||
d.recordIDsMu.Lock()
|
||||
recordID, ok := d.recordIDs[token]
|
||||
d.recordIDsMu.Unlock()
|
||||
if !ok {
|
||||
return fmt.Errorf("allinkl: unknown record ID for '%s' '%s'", fqdn, token)
|
||||
}
|
||||
|
||||
_, err = d.client.DeleteDNSSettings(credential, recordID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("allinkl: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
24
providers/dns/allinkl/allinkl.toml
Normal file
24
providers/dns/allinkl/allinkl.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
Name = "all-inkl"
|
||||
Description = ''''''
|
||||
URL = "https://all-inkl.com"
|
||||
Code = "allinkl"
|
||||
Since = "v4.5.0"
|
||||
|
||||
Example = '''
|
||||
ALL_INKL_LOGIN=xxxxxxxxxxxxxxxxxxxxxxxxxx \
|
||||
ALL_INKL_PASSWORD=yyyyyyyyyyyyyyyyyyyyyyyyyy \
|
||||
lego --email myemail@example.com --dns allinkl --domains my.example.org run
|
||||
'''
|
||||
|
||||
[Configuration]
|
||||
[Configuration.Credentials]
|
||||
ALL_INKL_API_KEY = "API login"
|
||||
ALL_INKL_PASSWORD = "API password"
|
||||
[Configuration.Additional]
|
||||
ALL_INKL_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||
ALL_INKL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||
ALL_INKL_HTTP_TIMEOUT = "API request timeout"
|
||||
|
||||
[Links]
|
||||
API = "https://kasapi.kasserver.com/dokumentation/phpdoc/index.html"
|
||||
Guide = "https://kasapi.kasserver.com/dokumentation/"
|
142
providers/dns/allinkl/allinkl_test.go
Normal file
142
providers/dns/allinkl/allinkl_test.go
Normal file
|
@ -0,0 +1,142 @@
|
|||
package allinkl
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-acme/lego/v4/platform/tester"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const envDomain = envNamespace + "DOMAIN"
|
||||
|
||||
var envTest = tester.NewEnvTest(EnvLogin, EnvPassword).WithDomain(envDomain)
|
||||
|
||||
func TestNewDNSProvider(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
envVars map[string]string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
envVars: map[string]string{
|
||||
EnvLogin: "user",
|
||||
EnvPassword: "secret",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "missing credentials: account name",
|
||||
envVars: map[string]string{
|
||||
EnvLogin: "",
|
||||
EnvPassword: "secret",
|
||||
},
|
||||
expected: "allinkl: some credentials information are missing: ALL_INKL_LOGIN",
|
||||
},
|
||||
{
|
||||
desc: "missing credentials: api key",
|
||||
envVars: map[string]string{
|
||||
EnvLogin: "user",
|
||||
EnvPassword: "",
|
||||
},
|
||||
expected: "allinkl: some credentials information are missing: ALL_INKL_PASSWORD",
|
||||
},
|
||||
{
|
||||
desc: "missing credentials: all",
|
||||
envVars: map[string]string{
|
||||
EnvLogin: "",
|
||||
EnvPassword: "",
|
||||
},
|
||||
expected: "allinkl: some credentials information are missing: ALL_INKL_LOGIN,ALL_INKL_PASSWORD",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
defer envTest.RestoreEnv()
|
||||
envTest.ClearEnv()
|
||||
|
||||
envTest.Apply(test.envVars)
|
||||
|
||||
p, err := NewDNSProvider()
|
||||
|
||||
if test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
require.NotNil(t, p.client)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDNSProviderConfig(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
login string
|
||||
password string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "success",
|
||||
login: "user",
|
||||
password: "secret",
|
||||
},
|
||||
{
|
||||
desc: "missing account name",
|
||||
password: "secret",
|
||||
expected: "allinkl: missing credentials",
|
||||
},
|
||||
{
|
||||
desc: "missing api key",
|
||||
login: "user",
|
||||
expected: "allinkl: missing credentials",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
config := NewDefaultConfig()
|
||||
config.Login = test.login
|
||||
config.Password = test.password
|
||||
|
||||
p, err := NewDNSProviderConfig(config)
|
||||
|
||||
if test.expected == "" {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NotNil(t, p.config)
|
||||
require.NotNil(t, p.client)
|
||||
} else {
|
||||
require.EqualError(t, err, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLivePresent(t *testing.T) {
|
||||
if !envTest.IsLiveTest() {
|
||||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
envTest.RestoreEnv()
|
||||
provider, err := NewDNSProvider()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = provider.Present(envTest.GetDomain(), "", "123d==")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLiveCleanUp(t *testing.T) {
|
||||
if !envTest.IsLiveTest() {
|
||||
t.Skip("skipping live test")
|
||||
}
|
||||
|
||||
envTest.RestoreEnv()
|
||||
provider, err := NewDNSProvider()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = provider.CleanUp(envTest.GetDomain(), "", "123d==")
|
||||
require.NoError(t, err)
|
||||
}
|
286
providers/dns/allinkl/internal/client.go
Normal file
286
providers/dns/allinkl/internal/client.go
Normal file
|
@ -0,0 +1,286 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
const (
|
||||
authEndpoint = "https://kasapi.kasserver.com/soap/KasAuth.php"
|
||||
apiEndpoint = "https://kasapi.kasserver.com/soap/KasApi.php"
|
||||
)
|
||||
|
||||
// Client a KAS server client.
|
||||
type Client struct {
|
||||
login string
|
||||
password string
|
||||
|
||||
authEndpoint string
|
||||
apiEndpoint string
|
||||
HTTPClient *http.Client
|
||||
floodTime time.Time
|
||||
}
|
||||
|
||||
// NewClient creates a new Client.
|
||||
func NewClient(login string, password string) *Client {
|
||||
return &Client{
|
||||
login: login,
|
||||
password: password,
|
||||
authEndpoint: authEndpoint,
|
||||
apiEndpoint: apiEndpoint,
|
||||
HTTPClient: &http.Client{Timeout: 10 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
// Authentication Creates a credential token.
|
||||
// - sessionLifetime: Validity of the token in seconds.
|
||||
// - sessionUpdateLifetime: with `true` the session is extended with every request.
|
||||
func (c Client) Authentication(sessionLifetime int, sessionUpdateLifetime bool) (string, error) {
|
||||
hash := sha1.New()
|
||||
hash.Write([]byte(c.password))
|
||||
|
||||
sul := "N"
|
||||
if sessionUpdateLifetime {
|
||||
sul = "Y"
|
||||
}
|
||||
|
||||
ar := AuthRequest{
|
||||
Login: c.login,
|
||||
AuthData: fmt.Sprintf("%x", hash.Sum(nil)),
|
||||
AuthType: "sha1",
|
||||
SessionLifetime: sessionLifetime,
|
||||
SessionUpdateLifetime: sul,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(ar)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("request marshal: %w", err)
|
||||
}
|
||||
|
||||
payload := []byte(strings.TrimSpace(fmt.Sprintf(kasAuthEnvelope, body)))
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, c.authEndpoint, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("request creation: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("request execution: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
return "", fmt.Errorf("invalid status code: %d %s", resp.StatusCode, string(data))
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("response read: %w", err)
|
||||
}
|
||||
|
||||
var e KasAuthEnvelope
|
||||
decoder := xml.NewTokenDecoder(Trimmer{decoder: xml.NewDecoder(bytes.NewReader(data))})
|
||||
err = decoder.Decode(&e)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("response xml decode: %w", err)
|
||||
}
|
||||
|
||||
if e.Body.Fault != nil {
|
||||
return "", e.Body.Fault
|
||||
}
|
||||
|
||||
return e.Body.KasAuthResponse.Return.Text, nil
|
||||
}
|
||||
|
||||
// GetDNSSettings Reading out the DNS settings of a zone.
|
||||
// - zone: host zone.
|
||||
// - recordID: the ID of the resource record (optional).
|
||||
func (c *Client) GetDNSSettings(credentialToken, zone, recordID string) ([]ReturnInfo, error) {
|
||||
requestParams := map[string]string{"zone_host": zone}
|
||||
|
||||
if recordID != "" {
|
||||
requestParams["record_id"] = recordID
|
||||
}
|
||||
|
||||
item, err := c.do(credentialToken, "get_dns_settings", requestParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw := getValue(item)
|
||||
|
||||
var g GetDNSSettingsAPIResponse
|
||||
err = mapstructure.Decode(raw, &g)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("response struct decode: %w", err)
|
||||
}
|
||||
|
||||
c.updateFloodTime(g.Response.KasFloodDelay)
|
||||
|
||||
return g.Response.ReturnInfo, nil
|
||||
}
|
||||
|
||||
// AddDNSSettings Creation of a DNS resource record.
|
||||
func (c *Client) AddDNSSettings(credentialToken string, record DNSRequest) (string, error) {
|
||||
item, err := c.do(credentialToken, "add_dns_settings", record)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
raw := getValue(item)
|
||||
|
||||
var g AddDNSSettingsAPIResponse
|
||||
err = mapstructure.Decode(raw, &g)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("response struct decode: %w", err)
|
||||
}
|
||||
|
||||
c.updateFloodTime(g.Response.KasFloodDelay)
|
||||
|
||||
return g.Response.ReturnInfo, nil
|
||||
}
|
||||
|
||||
// DeleteDNSSettings Deleting a DNS Resource Record.
|
||||
func (c *Client) DeleteDNSSettings(credentialToken, recordID string) (bool, error) {
|
||||
requestParams := map[string]string{"record_id": recordID}
|
||||
|
||||
item, err := c.do(credentialToken, "delete_dns_settings", requestParams)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
raw := getValue(item)
|
||||
|
||||
var g DeleteDNSSettingsAPIResponse
|
||||
err = mapstructure.Decode(raw, &g)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("response struct decode: %w", err)
|
||||
}
|
||||
|
||||
c.updateFloodTime(g.Response.KasFloodDelay)
|
||||
|
||||
return g.Response.ReturnInfo, nil
|
||||
}
|
||||
|
||||
func (c Client) do(credentialToken, action string, requestParams interface{}) (*Item, error) {
|
||||
time.Sleep(time.Until(c.floodTime))
|
||||
|
||||
ar := KasRequest{
|
||||
Login: c.login,
|
||||
AuthType: "session",
|
||||
AuthData: credentialToken,
|
||||
Action: action,
|
||||
RequestParams: requestParams,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(ar)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request marshal: %w", err)
|
||||
}
|
||||
|
||||
payload := []byte(strings.TrimSpace(fmt.Sprintf(kasAPIEnvelope, body)))
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, c.apiEndpoint, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request creation: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request execution: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("invalid status code: %d %s", resp.StatusCode, string(data))
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("response read: %w", err)
|
||||
}
|
||||
|
||||
var e KasAPIResponseEnvelope
|
||||
decoder := xml.NewTokenDecoder(Trimmer{decoder: xml.NewDecoder(bytes.NewReader(data))})
|
||||
err = decoder.Decode(&e)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("response xml decode: %w", err)
|
||||
}
|
||||
|
||||
if e.Body.Fault != nil {
|
||||
return nil, e.Body.Fault
|
||||
}
|
||||
|
||||
return e.Body.KasAPIResponse.Return, nil
|
||||
}
|
||||
|
||||
func (c *Client) updateFloodTime(delay float64) {
|
||||
c.floodTime = time.Now().Add(time.Duration(delay * float64(time.Second)))
|
||||
}
|
||||
|
||||
func getValue(item *Item) interface{} {
|
||||
switch {
|
||||
case item.Raw != "":
|
||||
v, _ := strconv.ParseBool(item.Raw)
|
||||
return v
|
||||
|
||||
case item.Text != "":
|
||||
switch item.Type {
|
||||
case "xsd:string":
|
||||
return item.Text
|
||||
case "xsd:float":
|
||||
v, _ := strconv.ParseFloat(item.Text, 64)
|
||||
return v
|
||||
case "xsd:int":
|
||||
v, _ := strconv.ParseInt(item.Text, 10, 64)
|
||||
return v
|
||||
default:
|
||||
return item.Text
|
||||
}
|
||||
|
||||
case item.Value != nil:
|
||||
return getValue(item.Value)
|
||||
|
||||
case len(item.Items) > 0 && item.Type == "SOAP-ENC:Array":
|
||||
var v []interface{}
|
||||
for _, i := range item.Items {
|
||||
v = append(v, getValue(i))
|
||||
}
|
||||
|
||||
return v
|
||||
|
||||
case len(item.Items) > 0:
|
||||
v := map[string]interface{}{}
|
||||
for _, i := range item.Items {
|
||||
v[getKey(i)] = getValue(i)
|
||||
}
|
||||
|
||||
return v
|
||||
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func getKey(item *Item) string {
|
||||
if item.Key == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.Key.Text
|
||||
}
|
194
providers/dns/allinkl/internal/client_test.go
Normal file
194
providers/dns/allinkl/internal/client_test.go
Normal file
|
@ -0,0 +1,194 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestClient_Authentication(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
mux.HandleFunc("/", testHandler("auth.xml"))
|
||||
|
||||
client := NewClient("user", "secret")
|
||||
client.authEndpoint = server.URL
|
||||
|
||||
credentialToken, err := client.Authentication(60, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "593959ca04f0de9689b586c6a647d15d", credentialToken)
|
||||
}
|
||||
|
||||
func TestClient_Authentication_error(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
mux.HandleFunc("/", testHandler("auth_fault.xml"))
|
||||
|
||||
client := NewClient("user", "secret")
|
||||
client.authEndpoint = server.URL
|
||||
|
||||
_, err := client.Authentication(60, false)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestClient_GetDNSSettings(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
mux.HandleFunc("/", testHandler("get_dns_settings.xml"))
|
||||
|
||||
client := NewClient("user", "secret")
|
||||
client.apiEndpoint = server.URL
|
||||
|
||||
token := "sha1secret"
|
||||
|
||||
records, err := client.GetDNSSettings(token, "example.com", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := []ReturnInfo{
|
||||
{
|
||||
ID: "57297429",
|
||||
Zone: "example.org",
|
||||
Name: "",
|
||||
Type: "A",
|
||||
Data: "10.0.0.1",
|
||||
Changeable: "Y",
|
||||
Aux: 0,
|
||||
},
|
||||
{
|
||||
ID: int64(0),
|
||||
Zone: "example.org",
|
||||
Name: "",
|
||||
Type: "NS",
|
||||
Data: "ns5.kasserver.com.",
|
||||
Changeable: "N",
|
||||
Aux: 0,
|
||||
},
|
||||
{
|
||||
ID: int64(0),
|
||||
Zone: "example.org",
|
||||
Name: "",
|
||||
Type: "NS",
|
||||
Data: "ns6.kasserver.com.",
|
||||
Changeable: "N",
|
||||
Aux: 0,
|
||||
},
|
||||
{
|
||||
ID: "57297479",
|
||||
Zone: "example.org",
|
||||
Name: "*",
|
||||
Type: "A",
|
||||
Data: "10.0.0.1",
|
||||
Changeable: "Y",
|
||||
Aux: 0,
|
||||
},
|
||||
{
|
||||
ID: "57297481",
|
||||
Zone: "example.org",
|
||||
Name: "",
|
||||
Type: "MX",
|
||||
Data: "user.kasserver.com.",
|
||||
Changeable: "Y",
|
||||
Aux: 10,
|
||||
},
|
||||
{
|
||||
ID: "57297483",
|
||||
Zone: "example.org",
|
||||
Name: "",
|
||||
Type: "TXT",
|
||||
Data: "v=spf1 mx a ?all",
|
||||
Changeable: "Y",
|
||||
Aux: 0,
|
||||
},
|
||||
{
|
||||
ID: "57297485",
|
||||
Zone: "example.org",
|
||||
Name: "_dmarc",
|
||||
Type: "TXT",
|
||||
Data: "v=DMARC1; p=none;",
|
||||
Changeable: "Y",
|
||||
Aux: 0,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, records)
|
||||
}
|
||||
|
||||
func TestClient_AddDNSSettings(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
mux.HandleFunc("/", testHandler("add_dns_settings.xml"))
|
||||
|
||||
client := NewClient("user", "secret")
|
||||
client.apiEndpoint = server.URL
|
||||
|
||||
token := "sha1secret"
|
||||
|
||||
record := DNSRequest{
|
||||
ZoneHost: "42cnc.de.",
|
||||
RecordType: "TXT",
|
||||
RecordName: "lego",
|
||||
RecordData: "abcdefgh",
|
||||
}
|
||||
|
||||
recordID, err := client.AddDNSSettings(token, record)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "57347444", recordID)
|
||||
}
|
||||
|
||||
func TestClient_DeleteDNSSettings(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
mux.HandleFunc("/", testHandler("delete_dns_settings.xml"))
|
||||
|
||||
client := NewClient("user", "secret")
|
||||
client.apiEndpoint = server.URL
|
||||
|
||||
token := "sha1secret"
|
||||
|
||||
r, err := client.DeleteDNSSettings(token, "57347450")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.True(t, r)
|
||||
}
|
||||
|
||||
func testHandler(filename string) http.HandlerFunc {
|
||||
return func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method != http.MethodPost {
|
||||
http.Error(rw, fmt.Sprintf("unsupported method: %s", req.Method), http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
file, err := os.Open(filepath.Join("fixtures", filename))
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = file.Close() }()
|
||||
|
||||
_, err = io.Copy(rw, file)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"Request": {
|
||||
"KasRequestParams": {
|
||||
"record_aux": 0,
|
||||
"record_data": "abcdefgh",
|
||||
"record_name": "lego",
|
||||
"record_type": "TXT",
|
||||
"zone_host": "example.org."
|
||||
},
|
||||
"KasRequestTime": 1625014992,
|
||||
"KasRequestType": true
|
||||
},
|
||||
"Response": {
|
||||
"KasFloodDelay": 0.5,
|
||||
"ReturnInfo": "57347444",
|
||||
"ReturnString": "TRUE"
|
||||
}
|
||||
}
|
68
providers/dns/allinkl/internal/fixtures/add_dns_settings.xml
Normal file
68
providers/dns/allinkl/internal/fixtures/add_dns_settings.xml
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:ns1="https://kasapi.kasserver.com/soap/KasApi.php"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:ns2="http://xml.apache.org/xml-soap"
|
||||
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
<ns1:KasApiResponse>
|
||||
<return xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Request</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestTime</key>
|
||||
<value xsi:type="xsd:int">1625014992</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestType</key>
|
||||
<value xsi:nil="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestParams</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">zone_host</key>
|
||||
<value xsi:type="xsd:string">example.org.</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">TXT</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string">lego</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">abcdefgh</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Response</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasFloodDelay</key>
|
||||
<value xsi:type="xsd:float">0.5</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnString</key>
|
||||
<value xsi:type="xsd:string">TRUE</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnInfo</key>
|
||||
<value xsi:type="xsd:string">57347444</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</return>
|
||||
</ns1:KasApiResponse>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
11
providers/dns/allinkl/internal/fixtures/auth.xml
Normal file
11
providers/dns/allinkl/internal/fixtures/auth.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:ns1="https://kasapi.kasserver.com/soap/KasAuth.php"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
<ns1:KasAuthResponse>
|
||||
<return xsi:type="xsd:string">593959ca04f0de9689b586c6a647d15d</return>
|
||||
</ns1:KasAuthResponse>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
10
providers/dns/allinkl/internal/fixtures/auth_fault.xml
Normal file
10
providers/dns/allinkl/internal/fixtures/auth_fault.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<SOAP-ENV:Body>
|
||||
<SOAP-ENV:Fault>
|
||||
<faultcode>SOAP-ENV:Client</faultcode>
|
||||
<faultstring>kas_login_syntax_incorrect</faultstring>
|
||||
<faultactor>KasAuth</faultactor>
|
||||
</SOAP-ENV:Fault>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"Request": {
|
||||
"KasRequestParams": {
|
||||
"record_id": "57347444"
|
||||
},
|
||||
"KasRequestTime": 1625016066,
|
||||
"KasRequestType": true
|
||||
},
|
||||
"Response": {
|
||||
"KasFloodDelay": 0.5,
|
||||
"ReturnInfo": true,
|
||||
"ReturnString": "TRUE"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:ns1="https://kasapi.kasserver.com/soap/KasApi.php"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:ns2="http://xml.apache.org/xml-soap"
|
||||
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
<ns1:KasApiResponse>
|
||||
<return xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Request</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestTime</key>
|
||||
<value xsi:type="xsd:int">1625016066</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestType</key>
|
||||
<value xsi:nil="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestParams</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57347444</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Response</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasFloodDelay</key>
|
||||
<value xsi:type="xsd:float">0.5</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnString</key>
|
||||
<value xsi:type="xsd:string">TRUE</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnInfo</key>
|
||||
<value xsi:nil="true"/>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</return>
|
||||
</ns1:KasApiResponse>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"Request": {
|
||||
"KasRequestParams": {
|
||||
"zone_host": "example.org"
|
||||
},
|
||||
"KasRequestTime": 1625012975,
|
||||
"KasRequestType": true
|
||||
},
|
||||
"Response": {
|
||||
"KasFloodDelay": 0.5,
|
||||
"ReturnInfo": [
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "Y",
|
||||
"record_data": "10.0.0.1",
|
||||
"record_id": "57297429",
|
||||
"record_name": "",
|
||||
"record_type": "A",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "N",
|
||||
"record_data": "ns5.kasserver.com.",
|
||||
"record_id": 0,
|
||||
"record_name": "",
|
||||
"record_type": "NS",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "N",
|
||||
"record_data": "ns6.kasserver.com.",
|
||||
"record_id": 0,
|
||||
"record_name": "",
|
||||
"record_type": "NS",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "Y",
|
||||
"record_data": "10.0.0.1",
|
||||
"record_id": "57297479",
|
||||
"record_name": "*",
|
||||
"record_type": "A",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 10,
|
||||
"record_changeable": "Y",
|
||||
"record_data": "user.kasserver.com.",
|
||||
"record_id": "57297481",
|
||||
"record_name": "",
|
||||
"record_type": "MX",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "Y",
|
||||
"record_data": "v=spf1 mx a ?all",
|
||||
"record_id": "57297483",
|
||||
"record_name": "",
|
||||
"record_type": "TXT",
|
||||
"record_zone": "example.org"
|
||||
},
|
||||
{
|
||||
"record_aux": 0,
|
||||
"record_changeable": "Y",
|
||||
"record_data": "v=DMARC1; p=none;",
|
||||
"record_id": "57297485",
|
||||
"record_name": "_dmarc",
|
||||
"record_type": "TXT",
|
||||
"record_zone": "example.org"
|
||||
}
|
||||
],
|
||||
"ReturnString": "TRUE"
|
||||
}
|
||||
}
|
263
providers/dns/allinkl/internal/fixtures/get_dns_settings.xml
Normal file
263
providers/dns/allinkl/internal/fixtures/get_dns_settings.xml
Normal file
|
@ -0,0 +1,263 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
|
||||
xmlns:ns1="https://kasapi.kasserver.com/soap/KasApi.php"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
|
||||
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<SOAP-ENV:Body>
|
||||
<ns1:KasApiResponse>
|
||||
<return xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Request</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestTime</key>
|
||||
<value xsi:type="xsd:int">1624993260</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestType</key>
|
||||
<value xsi:nil="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasRequestParams</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">zone_host</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">Response</key>
|
||||
<value xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">KasFloodDelay</key>
|
||||
<value xsi:type="xsd:float">0.5</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnString</key>
|
||||
<value xsi:type="xsd:string">TRUE</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">ReturnInfo</key>
|
||||
<value SOAP-ENC:arrayType="ns2:Map[7]" xsi:type="SOAP-ENC:Array">
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string"></value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">A</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">10.0.0.1</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57297429</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">Y</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string"></value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">NS</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">ns5.kasserver.com.</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">N</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string"></value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">NS</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">ns6.kasserver.com.</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">N</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string">*</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">A</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">10.0.0.1</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57297479</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">Y</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string"></value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">MX</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">user.kasserver.com.</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">10</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57297481</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">Y</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string"></value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">TXT</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">v=spf1 mx a ?all</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57297483</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">Y</value>
|
||||
</item>
|
||||
</item>
|
||||
<item xsi:type="ns2:Map">
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_zone</key>
|
||||
<value xsi:type="xsd:string">example.org</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_name</key>
|
||||
<value xsi:type="xsd:string">_dmarc</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_type</key>
|
||||
<value xsi:type="xsd:string">TXT</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_data</key>
|
||||
<value xsi:type="xsd:string">v=DMARC1; p=none;</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_aux</key>
|
||||
<value xsi:type="xsd:int">0</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_id</key>
|
||||
<value xsi:type="xsd:string">57297485</value>
|
||||
</item>
|
||||
<item>
|
||||
<key xsi:type="xsd:string">record_changeable</key>
|
||||
<value xsi:type="xsd:string">Y</value>
|
||||
</item>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</item>
|
||||
</return>
|
||||
</ns1:KasApiResponse>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
46
providers/dns/allinkl/internal/types.go
Normal file
46
providers/dns/allinkl/internal/types.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Trimmer trim all XML fields.
|
||||
type Trimmer struct {
|
||||
decoder *xml.Decoder
|
||||
}
|
||||
|
||||
func (tr Trimmer) Token() (xml.Token, error) {
|
||||
t, err := tr.decoder.Token()
|
||||
if cd, ok := t.(xml.CharData); ok {
|
||||
t = xml.CharData(bytes.TrimSpace(cd))
|
||||
}
|
||||
return t, err
|
||||
}
|
||||
|
||||
// Fault a SOAP fault.
|
||||
type Fault struct {
|
||||
Code string `xml:"faultcode"`
|
||||
Message string `xml:"faultstring"`
|
||||
Actor string `xml:"faultactor"`
|
||||
}
|
||||
|
||||
func (f Fault) Error() string {
|
||||
return fmt.Sprintf("%s: %s: %s", f.Actor, f.Code, f.Message)
|
||||
}
|
||||
|
||||
// KasResponse a KAS SOAP response.
|
||||
type KasResponse struct {
|
||||
Return *Item `xml:"return"`
|
||||
}
|
||||
|
||||
// Item an item of the KAS SOAP response.
|
||||
type Item struct {
|
||||
Text string `xml:",chardata" json:"text,omitempty"`
|
||||
Type string `xml:"type,attr" json:"type,omitempty"`
|
||||
Raw string `xml:"nil,attr" json:"raw,omitempty"`
|
||||
Key *Item `xml:"key" json:"key,omitempty"`
|
||||
Value *Item `xml:"value" json:"value,omitempty"`
|
||||
Items []*Item `xml:"item" json:"item,omitempty"`
|
||||
}
|
94
providers/dns/allinkl/internal/types_api.go
Normal file
94
providers/dns/allinkl/internal/types_api.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
package internal
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// kasAPIEnvelope a KAS API request envelope.
|
||||
const kasAPIEnvelope = `
|
||||
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<Body>
|
||||
<KasApi xmlns="https://kasserver.com/">
|
||||
<Params>%s</Params>
|
||||
</KasApi>
|
||||
</Body>
|
||||
</Envelope>`
|
||||
|
||||
// KasAPIResponseEnvelope a KAS envelope of the API response.
|
||||
type KasAPIResponseEnvelope struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Body KasAPIBody `xml:"Body"`
|
||||
}
|
||||
|
||||
type KasAPIBody struct {
|
||||
KasAPIResponse *KasResponse `xml:"KasApiResponse"`
|
||||
Fault *Fault `xml:"Fault"`
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type KasRequest struct {
|
||||
// Login the relevant KAS login.
|
||||
Login string `json:"kas_login,omitempty"`
|
||||
// AuthType the authentication type.
|
||||
AuthType string `json:"kas_auth_type,omitempty"`
|
||||
// AuthData the authentication data.
|
||||
AuthData string `json:"kas_auth_data,omitempty"`
|
||||
// Action API function.
|
||||
Action string `json:"kas_action,omitempty"`
|
||||
// RequestParams Parameters to the API function.
|
||||
RequestParams interface{} `json:"KasRequestParams,omitempty"`
|
||||
}
|
||||
|
||||
type DNSRequest struct {
|
||||
// ZoneHost the zone in question (must be a FQDN).
|
||||
ZoneHost string `json:"zone_host"`
|
||||
// RecordType the TYPE of the resource record (MX, A, AAAA etc.).
|
||||
RecordType string `json:"record_type"`
|
||||
// RecordName the NAME of the resource record.
|
||||
RecordName string `json:"record_name"`
|
||||
// RecordData the DATA of the resource record.
|
||||
RecordData string `json:"record_data"`
|
||||
// RecordAux the AUX of the resource record.
|
||||
RecordAux int `json:"record_aux"`
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type GetDNSSettingsAPIResponse struct {
|
||||
Response GetDNSSettingsResponse `json:"Response" mapstructure:"Response"`
|
||||
}
|
||||
|
||||
type GetDNSSettingsResponse struct {
|
||||
KasFloodDelay float64 `json:"KasFloodDelay" mapstructure:"KasFloodDelay"`
|
||||
ReturnInfo []ReturnInfo `json:"ReturnInfo" mapstructure:"ReturnInfo"`
|
||||
ReturnString string `json:"ReturnString"`
|
||||
}
|
||||
|
||||
type ReturnInfo struct {
|
||||
ID interface{} `json:"record_id,omitempty" mapstructure:"record_id"`
|
||||
Zone string `json:"record_zone,omitempty" mapstructure:"record_zone"`
|
||||
Name string `json:"record_name,omitempty" mapstructure:"record_name"`
|
||||
Type string `json:"record_type,omitempty" mapstructure:"record_type"`
|
||||
Data string `json:"record_data,omitempty" mapstructure:"record_data"`
|
||||
Changeable string `json:"record_changeable,omitempty" mapstructure:"record_changeable"`
|
||||
Aux int `json:"record_aux,omitempty" mapstructure:"record_aux"`
|
||||
}
|
||||
|
||||
type AddDNSSettingsAPIResponse struct {
|
||||
Response AddDNSSettingsResponse `json:"Response" mapstructure:"Response"`
|
||||
}
|
||||
|
||||
type AddDNSSettingsResponse struct {
|
||||
KasFloodDelay float64 `json:"KasFloodDelay" mapstructure:"KasFloodDelay"`
|
||||
ReturnInfo string `json:"ReturnInfo" mapstructure:"ReturnInfo"`
|
||||
ReturnString string `json:"ReturnString" mapstructure:"ReturnString"`
|
||||
}
|
||||
|
||||
type DeleteDNSSettingsAPIResponse struct {
|
||||
Response DeleteDNSSettingsResponse `json:"Response"`
|
||||
}
|
||||
|
||||
type DeleteDNSSettingsResponse struct {
|
||||
KasFloodDelay float64 `json:"KasFloodDelay"`
|
||||
ReturnInfo bool `json:"ReturnInfo"`
|
||||
ReturnString string `json:"ReturnString"`
|
||||
}
|
34
providers/dns/allinkl/internal/types_auth.go
Normal file
34
providers/dns/allinkl/internal/types_auth.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package internal
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// kasAuthEnvelope a KAS authentication request envelope.
|
||||
const kasAuthEnvelope = `
|
||||
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<Body>
|
||||
<KasAuth xmlns="https://kasserver.com/">
|
||||
<Params>%s</Params>
|
||||
</KasAuth>
|
||||
</Body>
|
||||
</Envelope>`
|
||||
|
||||
// KasAuthEnvelope a KAS envelope of the authentication response.
|
||||
type KasAuthEnvelope struct {
|
||||
XMLName xml.Name `xml:"Envelope"`
|
||||
Body KasAuthBody `xml:"Body"`
|
||||
}
|
||||
|
||||
type KasAuthBody struct {
|
||||
KasAuthResponse *KasResponse `xml:"KasAuthResponse"`
|
||||
Fault *Fault `xml:"Fault"`
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type AuthRequest struct {
|
||||
Login string `json:"kas_login,omitempty"`
|
||||
AuthData string `json:"kas_auth_data,omitempty"`
|
||||
AuthType string `json:"kas_auth_type,omitempty"`
|
||||
SessionLifetime int `json:"session_lifetime,omitempty"`
|
||||
SessionUpdateLifetime string `json:"session_update_lifetime,omitempty"`
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/providers/dns/acmedns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/alidns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/allinkl"
|
||||
"github.com/go-acme/lego/v4/providers/dns/arvancloud"
|
||||
"github.com/go-acme/lego/v4/providers/dns/auroradns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/autodns"
|
||||
|
@ -104,6 +105,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
|
|||
return acmedns.NewDNSProvider()
|
||||
case "alidns":
|
||||
return alidns.NewDNSProvider()
|
||||
case "allinkl":
|
||||
return allinkl.NewDNSProvider()
|
||||
case "arvancloud":
|
||||
return arvancloud.NewDNSProvider()
|
||||
case "azure":
|
||||
|
|
Loading…
Reference in a new issue