Skip to content

Commit

Permalink
Add DNS Provider for Tencent Cloud (#1527)
Browse files Browse the repository at this point in the history
  • Loading branch information
baranwang authored Dec 22, 2021
1 parent 0324783 commit 6907a39
Show file tree
Hide file tree
Showing 10 changed files with 489 additions and 3 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
| [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/) | [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/) | [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/) | |
| [Tencent Cloud DNS](https://go-acme.github.io/lego/dns/tencentcloud/) | [TransIP](https://go-acme.github.io/lego/dns/transip/) | [UKFast SafeDNS](https://go-acme.github.io/lego/dns/safedns/) | [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 -->

Expand Down
23 changes: 23 additions & 0 deletions cmd/zz_gen_cmd_dnshelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func allDNSCodes() string {
"simply",
"sonic",
"stackpath",
"tencentcloud",
"transip",
"vegadns",
"versio",
Expand Down Expand Up @@ -1997,6 +1998,28 @@ func displayDNSHelp(name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/stackpath`)

case "tencentcloud":
// generated from: providers/dns/tencentcloud/tencentcloud.toml
ew.writeln(`Configuration for Tencent Cloud DNS.`)
ew.writeln(`Code: 'tencentcloud'`)
ew.writeln(`Since: 'v4.6.0'`)
ew.writeln()

ew.writeln(`Credentials:`)
ew.writeln(` - "TENCENTCLOUD_SECRET_ID": Access key ID`)
ew.writeln(` - "TENCENTCLOUD_SECRET_KEY": Access Key secret`)
ew.writeln()

ew.writeln(`Additional Configuration:`)
ew.writeln(` - "TENCENTCLOUD_HTTP_TIMEOUT": API request timeout`)
ew.writeln(` - "TENCENTCLOUD_POLLING_INTERVAL": Time between DNS propagation check`)
ew.writeln(` - "TENCENTCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
ew.writeln(` - "TENCENTCLOUD_REGION": Region`)
ew.writeln(` - "TENCENTCLOUD_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/tencentcloud`)

case "transip":
// generated from: providers/dns/transip/transip.toml
ew.writeln(`Configuration for TransIP.`)
Expand Down
66 changes: 66 additions & 0 deletions docs/content/dns/zz_gen_tencentcloud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: "Tencent Cloud DNS"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: tencentcloud
---

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

Since: v4.6.0

Configuration for [Tencent Cloud DNS](https://cloud.tencent.com/product/cns).


<!--more-->

- Code: `tencentcloud`

Here is an example bash command using the Tencent Cloud DNS provider:

```bash
TENCENTCLOUD_SECRET_ID=abcdefghijklmnopqrstuvwx \
TENCENTCLOUD_SECRET_KEY=your-secret-key \
lego --email [email protected] --dns tencentcloud --domains my.example.org run
```




## Credentials

| Environment Variable Name | Description |
|-----------------------|-------------|
| `TENCENTCLOUD_SECRET_ID` | Access key ID |
| `TENCENTCLOUD_SECRET_KEY` | Access Key secret |

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 |
|--------------------------------|-------------|
| `TENCENTCLOUD_HTTP_TIMEOUT` | API request timeout |
| `TENCENTCLOUD_POLLING_INTERVAL` | Time between DNS propagation check |
| `TENCENTCLOUD_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
| `TENCENTCLOUD_REGION` | Region |
| `TENCENTCLOUD_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://cloud.tencent.com/document/product/1427/56153)
- [Go client](https://github.com/tencentcloud/tencentcloud-sdk-go)

<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/tencentcloud/tencentcloud.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ require (
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f
github.com/softlayer/softlayer-go v1.0.3
github.com/stretchr/testify v1.7.0
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287
github.com/transip/gotransip/v6 v6.6.1
github.com/urfave/cli v1.22.5
github.com/vinyldns/go-vinyldns v0.9.16
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,10 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287 h1:ohsyW4WffPdd2JLPio2Sd0qGr93hzkawAt9vWdCFLgY=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287 h1:O/ycBVvdOAmwFlXm0fCtLz2WOr1EaWZQTDM/4pmVT+s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287/go.mod h1:CuOaLxOQr477GhMWAQPYQFUJrsZbW+ZqkAgP2uHDZXg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/transip/gotransip/v6 v6.6.1 h1:nsCU1ErZS5G0FeOpgGXc4FsWvBff9GPswSMggsC4564=
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
Expand Down
3 changes: 3 additions & 0 deletions providers/dns/dns_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/simply"
"github.com/go-acme/lego/v4/providers/dns/sonic"
"github.com/go-acme/lego/v4/providers/dns/stackpath"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
"github.com/go-acme/lego/v4/providers/dns/transip"
"github.com/go-acme/lego/v4/providers/dns/vegadns"
"github.com/go-acme/lego/v4/providers/dns/versio"
Expand Down Expand Up @@ -286,6 +287,8 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return sonic.NewDNSProvider()
case "stackpath":
return stackpath.NewDNSProvider()
case "tencentcloud":
return tencentcloud.NewDNSProvider()
case "transip":
return transip.NewDNSProvider()
case "vegadns":
Expand Down
70 changes: 70 additions & 0 deletions providers/dns/tencentcloud/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package tencentcloud

import (
"strings"

"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
)

type domainData struct {
domain string
subDomain string
}

func getDomainData(fqdn string) (*domainData, error) {
zone, err := dns01.FindZoneByFqdn(fqdn)
if err != nil {
return nil, err
}

return &domainData{
domain: zone,
subDomain: dns01.UnFqdn(strings.TrimSuffix(fqdn, zone)),
}, nil
}

func (d *DNSProvider) createRecordData(domainData *domainData, value string) error {
request := dnspod.NewCreateRecordRequest()
request.Domain = common.StringPtr(domainData.domain)
request.SubDomain = common.StringPtr(domainData.subDomain)
request.RecordType = common.StringPtr("TXT")
request.RecordLine = common.StringPtr("默认")
request.Value = common.StringPtr(value)
request.TTL = common.Uint64Ptr(uint64(d.config.TTL))

_, err := d.client.CreateRecord(request)
if err != nil {
return err
}

return nil
}

func (d *DNSProvider) listRecordData(domainData *domainData) ([]*dnspod.RecordListItem, error) {
request := dnspod.NewDescribeRecordListRequest()
request.Domain = common.StringPtr(domainData.domain)
request.Subdomain = common.StringPtr(domainData.subDomain)
request.RecordType = common.StringPtr("TXT")

response, err := d.client.DescribeRecordList(request)
if err != nil {
return nil, err
}

return response.Response.RecordList, nil
}

func (d *DNSProvider) deleteRecordData(domainData *domainData, item *dnspod.RecordListItem) error {
request := dnspod.NewDeleteRecordRequest()
request.Domain = common.StringPtr(domainData.domain)
request.RecordId = item.RecordId

_, err := d.client.DeleteRecord(request)
if err != nil {
return err
}

return nil
}
142 changes: 142 additions & 0 deletions providers/dns/tencentcloud/tencentcloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Package tencentcloud implements a DNS provider for solving the DNS-01 challenge using Tencent Cloud DNS.
package tencentcloud

import (
"errors"
"fmt"
"time"

"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/platform/config/env"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
dnspod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod/v20210323"
)

// Environment variables names.
const (
envNamespace = "TENCENTCLOUD_"

EnvSecretID = envNamespace + "SECRET_ID"
EnvSecretKey = envNamespace + "SECRET_KEY"
EnvRegion = envNamespace + "REGION"

EnvTTL = envNamespace + "TTL"
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 {
SecretID string
SecretKey string
Region string

PropagationTimeout time.Duration
PollingInterval time.Duration
TTL int
HTTPTimeout time.Duration
}

// NewDefaultConfig returns a default configuration for the DNSProvider.
func NewDefaultConfig() *Config {
return &Config{
TTL: env.GetOrDefaultInt(EnvTTL, 600),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, dns01.DefaultPropagationTimeout),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 10*time.Second),
}
}

// DNSProvider implements the challenge.Provider interface.
type DNSProvider struct {
config *Config
client *dnspod.Client
}

// NewDNSProvider returns a DNSProvider instance configured for Tencent Cloud DNS.
// Credentials must be passed in the environment variable: TENCENTCLOUD_SECRET_ID, TENCENTCLOUD_SECRET_KEY.
func NewDNSProvider() (*DNSProvider, error) {
values, err := env.Get(EnvSecretID, EnvSecretKey)
if err != nil {
return nil, fmt.Errorf("tencentcloud: %w", err)
}

config := NewDefaultConfig()
config.SecretID = values[EnvSecretID]
config.SecretKey = values[EnvSecretKey]
config.Region = env.GetOrDefaultString(EnvRegion, "")

return NewDNSProviderConfig(config)
}

// NewDNSProviderConfig return a DNSProvider instance configured for Tencent Cloud DNS.
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
if config == nil {
return nil, errors.New("tencentcloud: the configuration of the DNS provider is nil")
}

if config.SecretID == "" || config.SecretKey == "" {
return nil, errors.New("tencentcloud: credentials missing")
}

credential := common.NewCredential(config.SecretID, config.SecretKey)

cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "dnspod.tencentcloudapi.com"

client, err := dnspod.NewClient(credential, config.Region, cpf)
if err != nil {
return nil, fmt.Errorf("tencentcloud: %w", err)
}

return &DNSProvider{config: config, client: client}, 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 to fulfill the dns-01 challenge.
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
fqdn, value := dns01.GetRecord(domain, keyAuth)

domainData, err := getDomainData(fqdn)
if err != nil {
return fmt.Errorf("tencentcloud: failed to get domain data: %w", err)
}

err = d.createRecordData(domainData, value)
if err != nil {
return fmt.Errorf("tencentcloud: create record failed: %w", err)
}

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)

domainData, err := getDomainData(fqdn)
if err != nil {
return fmt.Errorf("tencentcloud: failed to get domain data: %w", err)
}

records, err := d.listRecordData(domainData)
if err != nil {
return fmt.Errorf("tencentcloud: list records failed: %w", err)
}

for _, item := range records {
err := d.deleteRecordData(domainData, item)
if err != nil {
return fmt.Errorf("tencentcloud: delete record failed: %w", err)
}
}

return nil
}
26 changes: 26 additions & 0 deletions providers/dns/tencentcloud/tencentcloud.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Name = "Tencent Cloud DNS"
Description = ''''''
URL = "https://cloud.tencent.com/product/cns"
Code = "tencentcloud"
Since = "v4.6.0"

Example = '''
TENCENTCLOUD_SECRET_ID=abcdefghijklmnopqrstuvwx \
TENCENTCLOUD_SECRET_KEY=your-secret-key \
lego --email [email protected] --dns tencentcloud --domains my.example.org run
'''

[Configuration]
[Configuration.Credentials]
TENCENTCLOUD_SECRET_ID = "Access key ID"
TENCENTCLOUD_SECRET_KEY = "Access Key secret"
[Configuration.Additional]
TENCENTCLOUD_REGION = "Region"
TENCENTCLOUD_POLLING_INTERVAL = "Time between DNS propagation check"
TENCENTCLOUD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
TENCENTCLOUD_TTL = "The TTL of the TXT record used for the DNS challenge"
TENCENTCLOUD_HTTP_TIMEOUT = "API request timeout"

[Links]
API = "https://cloud.tencent.com/document/product/1427/56153"
GoClient = "https://github.com/tencentcloud/tencentcloud-sdk-go"
Loading

0 comments on commit 6907a39

Please sign in to comment.