183 lines
4.0 KiB
Go
183 lines
4.0 KiB
Go
package aliyun
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
dnsUtil2 "github.com/Mmx233/BitSrunLoginGo/internal/pkg/dns/util"
|
|
"github.com/Mmx233/tool"
|
|
"math/rand"
|
|
"net/http"
|
|
"net/url"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
type DnsProvider struct {
|
|
TTL uint `mapstructure:"-"`
|
|
Http *tool.Http `mapstructure:"-"`
|
|
AccessKeyId string `mapstructure:"access_key_id"`
|
|
AccessKeySecret string `mapstructure:"access_key_secret"`
|
|
}
|
|
|
|
func New(ttl uint, conf map[string]interface{}, Http *http.Client) (*DnsProvider, error) {
|
|
var p = DnsProvider{
|
|
TTL: ttl,
|
|
Http: tool.NewHttpTool(Http),
|
|
}
|
|
e := dnsUtil2.DecodeConfig(conf, &p)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
if p.AccessKeyId == "" || p.AccessKeySecret == "" {
|
|
return nil, errors.New("aliyun AccessKey 不能为空")
|
|
}
|
|
|
|
return &p, nil
|
|
}
|
|
|
|
func (a DnsProvider) SendRequest(Type, Action string, data map[string]interface{}) (*http.Response, error) {
|
|
var reqOpt = tool.DoHttpReq{
|
|
Url: "https://alidns.aliyuncs.com",
|
|
}
|
|
rand.Seed(time.Now().UnixNano())
|
|
data["Format"] = "json"
|
|
data["Version"] = "2015-01-09"
|
|
data["SignatureMethod"] = "HMAC-SHA1"
|
|
data["SignatureVersion"] = "1.0"
|
|
data["SignatureNonce"] = fmt.Sprint(tool.Rand.Num(10000000, 90000000))
|
|
data["Timestamp"] = time.Now().UTC().Format("2006-01-02T15:04:05Z")
|
|
data["Action"] = Action
|
|
data["AccessKeyId"] = a.AccessKeyId
|
|
|
|
signStr := Type + "&" + url.QueryEscape("/") + "&"
|
|
var keys = make([]string, len(data))
|
|
var i int
|
|
for k := range data {
|
|
keys[i] = k
|
|
i++
|
|
}
|
|
sort.Strings(keys)
|
|
for i, k := range keys {
|
|
str := k + "=" + url.QueryEscape(fmt.Sprint(data[k]))
|
|
if i == 0 {
|
|
str = url.QueryEscape(str)
|
|
} else {
|
|
str = url.QueryEscape("&" + str)
|
|
}
|
|
signStr += str
|
|
}
|
|
|
|
mac := hmac.New(sha1.New, []byte(a.AccessKeySecret+"&"))
|
|
_, e := mac.Write([]byte(signStr))
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
data["Signature"] = base64.StdEncoding.EncodeToString(mac.Sum(nil))
|
|
|
|
if Type == "GET" || Type == "DELETE" {
|
|
reqOpt.Query = data
|
|
} else {
|
|
reqOpt.Body = data
|
|
}
|
|
|
|
resp, e := a.Http.Request(Type, &reqOpt)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
if resp.StatusCode > 299 {
|
|
defer resp.Body.Close()
|
|
var res Response
|
|
if e = json.NewDecoder(resp.Body).Decode(&res); e != nil {
|
|
return nil, e
|
|
}
|
|
|
|
return nil, errors.New(res.Message)
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
func (a DnsProvider) DomainRecordStatus(subDomain, rootDomain string) (*DomainStatus, bool, error) {
|
|
resp, e := a.SendRequest("GET", "DescribeDomainRecords", map[string]interface{}{
|
|
"DomainName": rootDomain,
|
|
"SearchMode": "EXACT",
|
|
"KeyWord": subDomain,
|
|
"PageSize": 1,
|
|
"Type": "A",
|
|
})
|
|
if e != nil {
|
|
return nil, false, e
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var res DomainStatusRes
|
|
if e = json.NewDecoder(resp.Body).Decode(&res); e != nil {
|
|
return nil, false, e
|
|
}
|
|
|
|
if res.TotalCount == 0 || len(res.DomainRecords.Record) == 0 {
|
|
return nil, false, nil
|
|
}
|
|
|
|
return &res.DomainRecords.Record[0], true, nil
|
|
}
|
|
|
|
func (a DnsProvider) UpdateRecord(RecordId, subDomain, ip string) error {
|
|
resp, e := a.SendRequest("POST", "UpdateDomainRecord", map[string]interface{}{
|
|
"RecordId": RecordId,
|
|
"RR": subDomain,
|
|
"Type": "A",
|
|
"Value": ip,
|
|
"TTL": a.TTL,
|
|
})
|
|
if e != nil {
|
|
return e
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a DnsProvider) NewRecord(subDomain, rootDomain, ip string) error {
|
|
resp, e := a.SendRequest("POST", "AddDomainRecord", map[string]interface{}{
|
|
"DomainName": rootDomain,
|
|
"RR": subDomain,
|
|
"Type": "A",
|
|
"Value": ip,
|
|
"TTL": a.TTL,
|
|
})
|
|
if e != nil {
|
|
return e
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a DnsProvider) SetDomainRecord(domain, ip string) error {
|
|
subDomain, rootDomain, e := dnsUtil2.DecodeDomain(domain)
|
|
if e != nil {
|
|
return e
|
|
}
|
|
|
|
record, exist, e := a.DomainRecordStatus(subDomain, rootDomain)
|
|
if e != nil {
|
|
return e
|
|
}
|
|
|
|
if exist {
|
|
if record.Value == ip {
|
|
return nil
|
|
}
|
|
return a.UpdateRecord(record.RecordId, subDomain, ip)
|
|
} else {
|
|
return a.NewRecord(subDomain, rootDomain, ip)
|
|
}
|
|
}
|