mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 09:21:56 +08:00
feat: add baiducloud dns-01 applicant
This commit is contained in:
parent
c451bf5e03
commit
1bac6174ad
@ -90,6 +90,7 @@ make local.run
|
||||
| :----------------------------------------------------------------- | :-------------------------------------- |
|
||||
| [阿里云](https://www.aliyun.com/) | |
|
||||
| [腾讯云](https://cloud.tencent.com/) | |
|
||||
| [百度智能云](https://cloud.baidu.com/) | |
|
||||
| [华为云](https://www.huaweicloud.com/) | |
|
||||
| [火山引擎](https://www.volcengine.com/) | |
|
||||
| [AWS Route53](https://aws.amazon.com/route53/) | |
|
||||
|
@ -89,6 +89,7 @@ The following DNS providers are supported:
|
||||
| :----------------------------------------------------------- | :------------------------------------ |
|
||||
| [Alibaba Cloud](https://www.alibabacloud.com/) | |
|
||||
| [Tencent Cloud](https://www.tencentcloud.com/) | |
|
||||
| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | |
|
||||
| [Huawei Cloud](https://www.huaweicloud.com/) | |
|
||||
| [Volcengine](https://www.volcengine.com/) | |
|
||||
| [AWS Route53](https://aws.amazon.com/route53/) | |
|
||||
|
2
go.mod
2
go.mod
@ -19,7 +19,7 @@ require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||
github.com/aws/aws-sdk-go-v2/service/acm v1.30.18
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.44.10
|
||||
github.com/baidubce/bce-sdk-go v0.9.216
|
||||
github.com/baidubce/bce-sdk-go v0.9.217
|
||||
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.41
|
||||
github.com/go-acme/lego/v4 v4.21.0
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
|
2
go.sum
2
go.sum
@ -261,6 +261,8 @@ github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/baidubce/bce-sdk-go v0.9.216 h1:jRq4C1UGYcvHo6Gst2kuUzhWwJM6EqXCmhIsTKQvf4k=
|
||||
github.com/baidubce/bce-sdk-go v0.9.216/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/baidubce/bce-sdk-go v0.9.217 h1:dbMeVzpr9BGItTFHB1s2KSrpz0ayJC1y366VUMmaF0k=
|
||||
github.com/baidubce/bce-sdk-go v0.9.217/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun"
|
||||
pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53"
|
||||
pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns"
|
||||
pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud"
|
||||
pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare"
|
||||
pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns"
|
||||
pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore"
|
||||
@ -102,6 +103,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
|
||||
return applicant, err
|
||||
}
|
||||
|
||||
case domain.ApplyDNSProviderTypeBaiduCloud, domain.ApplyDNSProviderTypeBaiduCloudDNS:
|
||||
{
|
||||
access := domain.AccessConfigForBaiduCloud{}
|
||||
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
applicant, err := pBaiduCloud.NewChallengeProvider(&pBaiduCloud.BaiduCloudApplicantConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
SecretAccessKey: access.SecretAccessKey,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return applicant, err
|
||||
}
|
||||
|
||||
case domain.ApplyDNSProviderTypeCloudflare:
|
||||
{
|
||||
access := domain.AccessConfigForCloudflare{}
|
||||
|
@ -67,6 +67,8 @@ const (
|
||||
ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53]
|
||||
ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53")
|
||||
ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns")
|
||||
ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS]
|
||||
ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns")
|
||||
ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare")
|
||||
ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns")
|
||||
ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore")
|
||||
|
@ -0,0 +1,39 @@
|
||||
package baiducloud
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
|
||||
internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal"
|
||||
)
|
||||
|
||||
type BaiduCloudApplicantConfig struct {
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int32 `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallengeProvider(config *BaiduCloudApplicantConfig) (challenge.Provider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
providerConfig := internal.NewDefaultConfig()
|
||||
providerConfig.AccessKeyID = config.AccessKeyId
|
||||
providerConfig.SecretAccessKey = config.SecretAccessKey
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = config.DnsTTL
|
||||
}
|
||||
|
||||
provider, err := internal.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
package lego_baiducloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
bceDns "github.com/baidubce/bce-sdk-go/services/dns"
|
||||
"github.com/go-acme/lego/v4/challenge"
|
||||
"github.com/go-acme/lego/v4/challenge/dns01"
|
||||
"github.com/go-acme/lego/v4/platform/config/env"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
envNamespace = "BAIDUCLOUD_"
|
||||
|
||||
EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID"
|
||||
EnvSecretAccessKey = envNamespace + "SECRET_ACCESS_KEY"
|
||||
|
||||
EnvTTL = envNamespace + "TTL"
|
||||
EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
|
||||
EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
|
||||
EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
|
||||
)
|
||||
|
||||
var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
|
||||
|
||||
type Config struct {
|
||||
AccessKeyID string
|
||||
SecretAccessKey string
|
||||
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int32
|
||||
HTTPTimeout time.Duration
|
||||
}
|
||||
|
||||
type DNSProvider struct {
|
||||
client *bceDns.Client
|
||||
config *Config
|
||||
}
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
func NewDNSProvider() (*DNSProvider, error) {
|
||||
values, err := env.Get(EnvAccessKeyID, EnvSecretAccessKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("baiducloud: %w", err)
|
||||
}
|
||||
|
||||
config := NewDefaultConfig()
|
||||
config.AccessKeyID = values[EnvAccessKeyID]
|
||||
config.SecretAccessKey = values[EnvSecretAccessKey]
|
||||
|
||||
return NewDNSProviderConfig(config)
|
||||
}
|
||||
|
||||
func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("baiducloud: the configuration of the DNS provider is nil")
|
||||
}
|
||||
|
||||
client, err := bceDns.NewClient(config.AccessKeyID, config.SecretAccessKey, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if client.Config != nil {
|
||||
client.Config.ConnectionTimeoutInMillis = int(config.HTTPTimeout.Milliseconds())
|
||||
}
|
||||
}
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
info := dns01.GetChallengeInfo(domain, keyAuth)
|
||||
|
||||
zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("baiducloud: %w", err)
|
||||
}
|
||||
|
||||
subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("baiducloud: %w", err)
|
||||
}
|
||||
|
||||
if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil {
|
||||
return fmt.Errorf("baiducloud: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
subDomain := dns01.UnFqdn(fqdn)
|
||||
|
||||
if err := d.removeDNSRecord(domain, subDomain, value); err != nil {
|
||||
return fmt.Errorf("baiducloud: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||
}
|
||||
|
||||
func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*bceDns.Record, error) {
|
||||
pageMarker := ""
|
||||
pageSize := 1000
|
||||
for {
|
||||
request := &bceDns.ListRecordRequest{}
|
||||
request.Rr = domain
|
||||
request.Marker = pageMarker
|
||||
request.MaxKeys = pageSize
|
||||
|
||||
response, err := d.client.ListRecord(domain, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, record := range response.Records {
|
||||
if record.Type == "TXT" && record.Rr == subDomain {
|
||||
return &record, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.Records) < pageSize {
|
||||
break
|
||||
}
|
||||
|
||||
pageMarker = response.NextMarker
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error {
|
||||
record, err := d.getDNSRecord(domain, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
request := &bceDns.CreateRecordRequest{
|
||||
Type: "TXT",
|
||||
Rr: subDomain,
|
||||
Value: value,
|
||||
Ttl: &d.config.TTL,
|
||||
}
|
||||
err := d.client.CreateRecord(domain, request, d.generateClientToken())
|
||||
return err
|
||||
} else {
|
||||
request := &bceDns.UpdateRecordRequest{
|
||||
Type: "TXT",
|
||||
Rr: subDomain,
|
||||
Value: value,
|
||||
Ttl: &d.config.TTL,
|
||||
}
|
||||
err := d.client.UpdateRecord(domain, record.Id, request, d.generateClientToken())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error {
|
||||
record, err := d.getDNSRecord(domain, subDomain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = d.client.DeleteRecord(domain, record.Id, d.generateClientToken())
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DNSProvider) generateClientToken() string {
|
||||
return strings.ReplaceAll(uuid.New().String(), "-", "")
|
||||
}
|
@ -207,8 +207,3 @@ func Populate(dict map[string]any, output any) error {
|
||||
|
||||
return decoder.Decode(dict)
|
||||
}
|
||||
|
||||
// Deprecated: Use [Populate] instead.
|
||||
func Decode(dict map[string]any, output any) error {
|
||||
return Populate(dict, output)
|
||||
}
|
||||
|
5
main.go
5
main.go
@ -29,6 +29,11 @@ func main() {
|
||||
var flagDir string
|
||||
flag.StringVar(&flagHttp, "http", "127.0.0.1:8090", "HTTP server address")
|
||||
flag.StringVar(&flagDir, "dir", "/pb_data/database", "Pocketbase data directory")
|
||||
if len(os.Args) < 2 {
|
||||
slog.Error("[CERTIMATE] missing exec args")
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
_ = flag.CommandLine.Parse(os.Args[2:]) // skip the first two arguments: "main.go serve"
|
||||
|
||||
migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{
|
||||
|
@ -67,11 +67,11 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.KUBERNETES, "provider.kubernetes", "/imgs/providers/kubernetes.svg", [ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.ALIYUN, "provider.aliyun", "/imgs/providers/aliyun.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.TENCENTCLOUD, "provider.tencentcloud", "/imgs/providers/tencentcloud.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.BAIDUCLOUD, "provider.baiducloud", "/imgs/providers/baiducloud.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.HUAWEICLOUD, "provider.huaweicloud", "/imgs/providers/huaweicloud.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.VOLCENGINE, "provider.volcengine", "/imgs/providers/volcengine.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.AWS, "provider.aws", "/imgs/providers/aws.svg", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.GCORE, "provider.gcore", "/imgs/providers/gcore.png", [ACCESS_USAGES.APPLY, ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.BAIDUCLOUD, "provider.baiducloud", "/imgs/providers/baiducloud.svg", [ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.QINIU, "provider.qiniu", "/imgs/providers/qiniu.svg", [ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.BAISHAN, "provider.baishan", "/imgs/providers/baishan.png", [ACCESS_USAGES.DEPLOY]],
|
||||
[ACCESS_PROVIDERS.DOGECLOUD, "provider.dogecloud", "/imgs/providers/dogecloud.png", [ACCESS_USAGES.DEPLOY]],
|
||||
@ -118,6 +118,8 @@ export const APPLY_DNS_PROVIDERS = Object.freeze({
|
||||
AWS: `${ACCESS_PROVIDERS.AWS}`, // 兼容旧值,等同于 `AWS_ROUTE53`
|
||||
AWS_ROUTE53: `${ACCESS_PROVIDERS.AWS}-route53`,
|
||||
AZURE_DNS: `${ACCESS_PROVIDERS.AZURE}-dns`,
|
||||
BAIDUCLOUD: `${ACCESS_PROVIDERS.BAIDUCLOUD}`, // 兼容旧值,等同于 `BAIDUCLOUD_DNS`
|
||||
BAIDUCLOUD_DNS: `${ACCESS_PROVIDERS.BAIDUCLOUD}-dns`,
|
||||
CLOUDFLARE: `${ACCESS_PROVIDERS.CLOUDFLARE}`,
|
||||
CLOUDNS: `${ACCESS_PROVIDERS.CLOUDNS}`,
|
||||
GCORE: `${ACCESS_PROVIDERS.GCORE}`,
|
||||
@ -154,6 +156,7 @@ export const applyDNSProvidersMap: Map<ApplyDNSProvider["type"] | string, ApplyD
|
||||
[
|
||||
[APPLY_DNS_PROVIDERS.ALIYUN_DNS, "provider.aliyun.dns"],
|
||||
[APPLY_DNS_PROVIDERS.TENCENTCLOUD_DNS, "provider.tencentcloud.dns"],
|
||||
[APPLY_DNS_PROVIDERS.BAIDUCLOUD_DNS, "provider.baiducloud.dns"],
|
||||
[APPLY_DNS_PROVIDERS.HUAWEICLOUD_DNS, "provider.huaweicloud.dns"],
|
||||
[APPLY_DNS_PROVIDERS.VOLCENGINE_DNS, "provider.volcengine.dns"],
|
||||
[APPLY_DNS_PROVIDERS.AWS_ROUTE53, "provider.aws.route53"],
|
||||
|
@ -22,6 +22,7 @@
|
||||
"provider.azure.dns": "Azure - DNS",
|
||||
"provider.baiducloud": "Baidu Cloud",
|
||||
"provider.baiducloud.cdn": "Baidu Cloud - CDN (Content Delivery Network)",
|
||||
"provider.baiducloud.dns": "Baidu Cloud - DNS (Domain Name Service)",
|
||||
"provider.baishan": "Baishan",
|
||||
"provider.baishan.cdn": "Baishan - CDN (Content Delivery Network)",
|
||||
"provider.baotapanel": "BaoTa Panel",
|
||||
|
@ -22,6 +22,7 @@
|
||||
"provider.azure.dns": "Azure - DNS",
|
||||
"provider.baiducloud": "百度智能云",
|
||||
"provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
|
||||
"provider.baiducloud.dns": "百度智能云 - 智能云解析 DNS",
|
||||
"provider.baishan": "白山云",
|
||||
"provider.baishan.cdn": "白山云 - 内容分发网络 CDN",
|
||||
"provider.baotapanel": "宝塔面板",
|
||||
|
Loading…
x
Reference in New Issue
Block a user