Skip to content

Commit

Permalink
Add DNS provider for wedos (#1385)
Browse files Browse the repository at this point in the history
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
  • Loading branch information
lubko and ldez authored Apr 13, 2021
1 parent 7f53f88 commit 9002e5c
Show file tree
Hide file tree
Showing 15 changed files with 964 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
| [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/) | [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/) | [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/) | | | |
| [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 -->
22 changes: 22 additions & 0 deletions cmd/zz_gen_cmd_dnshelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func allDNSCodes() string {
"vinyldns",
"vscale",
"vultr",
"wedos",
"yandex",
"zoneee",
"zonomi",
Expand Down Expand Up @@ -1830,6 +1831,27 @@ func displayDNSHelp(name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/vultr`)

case "wedos":
// generated from: providers/dns/wedos/wedos.toml
ew.writeln(`Configuration for WEDOS.`)
ew.writeln(`Code: 'wedos'`)
ew.writeln(`Since: 'v4.4.0'`)
ew.writeln()

ew.writeln(`Credentials:`)
ew.writeln(` - "WEDOS_USERNAME": Username is the same as for the admin account`)
ew.writeln(` - "WEDOS_WAPI_PASSWORD": Password needs to be generated and IP allowed in the admin interface`)
ew.writeln()

ew.writeln(`Additional Configuration:`)
ew.writeln(` - "WEDOS_HTTP_TIMEOUT": API request timeout`)
ew.writeln(` - "WEDOS_POLLING_INTERVAL": Time between DNS propagation check`)
ew.writeln(` - "WEDOS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
ew.writeln(` - "WEDOS_TTL": The TTL of the TXT record used for the DNS challenge`)

ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/wedos`)

case "yandex":
// generated from: providers/dns/yandex/yandex.toml
ew.writeln(`Configuration for Yandex.`)
Expand Down
64 changes: 64 additions & 0 deletions docs/content/dns/zz_gen_wedos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: "WEDOS"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: wedos
---

<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/wedos/wedos.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

Since: v4.4.0

Configuration for [WEDOS](https://www.wedos.com).


<!--more-->

- Code: `wedos`

Here is an example bash command using the WEDOS provider:

```bash
WEDOS_USERNAME=xxxxxxxx \
WEDOS_WAPI_PASSWORD=xxxxxxxx \
lego -email myemail@example.com --dns wedos --domains my.example.org -run
```




## Credentials

| Environment Variable Name | Description |
|-----------------------|-------------|
| `WEDOS_USERNAME` | Username is the same as for the admin account |
| `WEDOS_WAPI_PASSWORD` | Password needs to be generated and IP allowed in the admin interface |

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 |
|--------------------------------|-------------|
| `WEDOS_HTTP_TIMEOUT` | API request timeout |
| `WEDOS_POLLING_INTERVAL` | Time between DNS propagation check |
| `WEDOS_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
| `WEDOS_TTL` | The TTL of the TXT record used for the DNS challenge |

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://kb.wedos.com/en/kategorie/wapi-api-interface/wdns-en/)

<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/wedos/wedos.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
3 changes: 3 additions & 0 deletions providers/dns/dns_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/vinyldns"
"github.com/go-acme/lego/v4/providers/dns/vscale"
"github.com/go-acme/lego/v4/providers/dns/vultr"
"github.com/go-acme/lego/v4/providers/dns/wedos"
"github.com/go-acme/lego/v4/providers/dns/yandex"
"github.com/go-acme/lego/v4/providers/dns/zoneee"
"github.com/go-acme/lego/v4/providers/dns/zonomi"
Expand Down Expand Up @@ -258,6 +259,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return vinyldns.NewDNSProvider()
case "vscale":
return vscale.NewDNSProvider()
case "wedos":
return wedos.NewDNSProvider()
case "yandex":
return yandex.NewDNSProvider()
case "zoneee":
Expand Down
215 changes: 215 additions & 0 deletions providers/dns/wedos/internal/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package internal

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"

"github.com/go-acme/lego/v4/challenge/dns01"
)

const baseURL = "https://api.wedos.com/wapi/json"

const codeOk = 1000

const (
commandPing = "ping"
commandDNSDomainCommit = "dns-domain-commit"
commandDNSRowsList = "dns-rows-list"
commandDNSRowDelete = "dns-row-delete"
commandDNSRowAdd = "dns-row-add"
commandDNSRowUpdate = "dns-row-update"
)

type ResponsePayload struct {
Code int `json:"code,omitempty"`
Result string `json:"result,omitempty"`
Timestamp int `json:"timestamp,omitempty"`
SvTRID string `json:"svTRID,omitempty"`
Command string `json:"command,omitempty"`
Data json.RawMessage `json:"data"`
DNSRowsList []DNSRow
}

type DNSRow struct {
ID string `json:"ID,omitempty"`
Domain string `json:"domain,omitempty"`
Name string `json:"name,omitempty"`
TTL json.Number `json:"ttl,omitempty" type:"integer"`
Type string `json:"rdtype,omitempty"`
Data string `json:"rdata"`
}

type APIRequest struct {
User string `json:"user,omitempty"`
Auth string `json:"auth,omitempty"`
Command string `json:"command,omitempty"`
Data interface{} `json:"data,omitempty"`
}

type Client struct {
username string
password string
baseURL string
HTTPClient *http.Client
}

func NewClient(username string, password string) *Client {
return &Client{
username: username,
password: password,
baseURL: baseURL,
HTTPClient: &http.Client{Timeout: 10 * time.Second},
}
}

// GetRecords lists all the records in the zone.
// https://kb.wedos.com/en/wapi-api-interface/wapi-command-dns-rows-list/
func (c *Client) GetRecords(ctx context.Context, zone string) ([]DNSRow, error) {
payload := map[string]interface{}{
"domain": dns01.UnFqdn(zone),
}

resp, err := c.do(ctx, commandDNSRowsList, payload)
if err != nil {
return nil, err
}

arrayWrapper := struct {
Rows []DNSRow `json:"row"`
}{}

err = json.Unmarshal(resp.Data, &arrayWrapper)
if err != nil {
return nil, err
}

return arrayWrapper.Rows, err
}

// AddRecord adds a record in the zone, either by updating existing records or creating new ones.
// https://kb.wedos.com/en/wapi-api-interface/wapi-command-dns-add-row/
// https://kb.wedos.com/en/wapi-api-interface/wapi-command-dns-row-update/
func (c *Client) AddRecord(ctx context.Context, zone string, record DNSRow) error {
payload := DNSRow{
Domain: dns01.UnFqdn(zone),
TTL: record.TTL,
Type: record.Type,
Data: record.Data,
}

cmd := commandDNSRowAdd
if record.ID == "" {
payload.Name = record.Name
} else {
cmd = commandDNSRowUpdate
payload.ID = record.ID
}

_, err := c.do(ctx, cmd, payload)
if err != nil {
return err
}

return nil
}

// DeleteRecord deletes a record from the zone.
// If a record does not have an ID, it will be looked up.
// https://kb.wedos.com/en/wapi-api-interface/wapi-command-dns-row-delete/
func (c *Client) DeleteRecord(ctx context.Context, zone string, recordID string) error {
payload := DNSRow{
Domain: dns01.UnFqdn(zone),
ID: recordID,
}

_, err := c.do(ctx, commandDNSRowDelete, payload)
if err != nil {
return err
}

return nil
}

// Commit not really required, all changes will be auto-committed after 5 minutes.
// https://kb.wedos.com/en/wapi-api-interface/wapi-command-dns-domain-commit/
func (c *Client) Commit(ctx context.Context, zone string) error {
payload := map[string]interface{}{
"name": dns01.UnFqdn(zone),
}

_, err := c.do(ctx, commandDNSDomainCommit, payload)
if err != nil {
return err
}

return nil
}

func (c *Client) Ping(ctx context.Context) error {
_, err := c.do(ctx, commandPing, nil)
if err != nil {
return err
}

return nil
}

func (c *Client) do(ctx context.Context, command string, payload interface{}) (*ResponsePayload, error) {
requestObject := map[string]interface{}{
"request": APIRequest{
User: c.username,
Auth: authToken(c.username, c.password),
Command: command,
Data: payload,
},
}

jsonBytes, err := json.Marshal(requestObject)
if err != nil {
return nil, err
}

form := url.Values{}
form.Add("request", string(jsonBytes))

req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, strings.NewReader(form.Encode()))
if err != nil {
return nil, err
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

resp, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

if resp.StatusCode/100 != 2 {
return nil, fmt.Errorf("API error, status code: %d", resp.StatusCode)
}

responseWrapper := struct {
Response ResponsePayload `json:"response"`
}{}

err = json.Unmarshal(body, &responseWrapper)
if err != nil {
return nil, err
}

if responseWrapper.Response.Code != codeOk {
return nil, fmt.Errorf("wedos responded with error code %d = %s", responseWrapper.Response.Code, responseWrapper.Response.Result)
}

return &responseWrapper.Response, err
}
Loading

0 comments on commit 9002e5c

Please sign in to comment.