Skip to content

Commit 522cc7c

Browse files
authored
chore(aliyun): remove Alibaba SDK dependency (#253)
- Remove `region` parameter - Support AAAA records - Files split around
1 parent 519b9c4 commit 522cc7c

File tree

9 files changed

+283
-57
lines changed

9 files changed

+283
-57
lines changed

docs/aliyun.md

-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"host": "@",
1414
"access_key_id": "your access_key_id",
1515
"access_secret": "your access_secret",
16-
"region": "your region",
1716
"ip_version": "ipv4"
1817
}
1918
]
@@ -30,6 +29,5 @@
3029
### Optional parameters
3130

3231
- `"ip_version"` can be `ipv4` (A records) or `ipv6` (AAAA records), defaults to `ipv4 or ipv6`
33-
- `"region"` is your region, which defaults to `cn-hangzhou` if not set.
3432

3533
## Domain setup

go.mod

-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ module github.com/qdm12/ddns-updater
33
go 1.20
44

55
require (
6-
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1280
76
github.com/breml/rootcerts v0.2.0
87
github.com/containrrr/shoutrrr v0.5.1
98
github.com/go-chi/chi v1.5.4
@@ -27,12 +26,8 @@ require (
2726
github.com/google/uuid v1.3.0 // indirect
2827
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
2928
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
30-
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
31-
github.com/json-iterator/go v1.1.9 // indirect
3229
github.com/mattn/go-colorable v0.1.9 // indirect
3330
github.com/mattn/go-isatty v0.0.14 // indirect
34-
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
35-
github.com/modern-go/reflect2 v1.0.1 // indirect
3631
github.com/nxadm/tail v1.4.6 // indirect
3732
github.com/onsi/ginkgo v1.14.2 // indirect
3833
github.com/onsi/gomega v1.10.1 // indirect
@@ -48,7 +43,6 @@ require (
4843
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f // indirect
4944
google.golang.org/grpc v1.47.0 // indirect
5045
google.golang.org/protobuf v1.28.0 // indirect
51-
gopkg.in/ini.v1 v1.62.0 // indirect
5246
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
5347
gopkg.in/yaml.v2 v2.3.0 // indirect
5448
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

go.sum

-16
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
6161
github.com/agnivade/wasmbrowsertest v0.3.1/go.mod h1:zQt6ZTdl338xxRaMW395qccVE2eQm0SjC/SDz0mPWQI=
6262
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
6363
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
64-
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1280 h1:2NvK2j7P4yuxBp2hoJ1UMpmrYY+na8M/0+IP60vdiww=
65-
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1280/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ=
6664
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
6765
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
6866
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -148,7 +146,6 @@ github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
148146
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
149147
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
150148
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
151-
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
152149
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
153150
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
154151
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -240,7 +237,6 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99
240237
github.com/googleapis/gax-go/v2 v2.4.0 h1:dS9eYAjhrE2RjmzYw2XAPvcXfmcQLtFEQWn0CR82awk=
241238
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
242239
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
243-
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
244240
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
245241
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
246242
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -257,15 +253,10 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
257253
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
258254
github.com/jarcoal/httpmock v1.0.4 h1:jp+dy/+nonJE4g4xbVtl9QdrUNbn6/3hDT5R4nDIZnA=
259255
github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
260-
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
261-
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
262256
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
263-
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
264-
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
265257
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
266258
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
267259
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
268-
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
269260
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
270261
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
271262
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@@ -307,10 +298,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
307298
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
308299
github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
309300
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
310-
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
311-
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
312301
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
313-
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
314302
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
315303
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
316304
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -361,9 +349,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
361349
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
362350
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
363351
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
364-
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
365352
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
366-
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
367353
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
368354
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
369355
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -887,8 +873,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
887873
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
888874
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
889875
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
890-
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
891-
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
892876
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
893877
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
894878
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package aliyun
2+
3+
//nolint:gosec
4+
import (
5+
"crypto/hmac"
6+
"crypto/sha1"
7+
"encoding/base64"
8+
"net/url"
9+
"sort"
10+
"strings"
11+
)
12+
13+
func sign(method string, urlValues url.Values, accessKeySecret string) {
14+
sortedParams := make(sort.StringSlice, 0, len(urlValues))
15+
for key, values := range urlValues {
16+
s := url.QueryEscape(key) + "=" + url.QueryEscape(values[0])
17+
sortedParams = append(sortedParams, s)
18+
}
19+
sortedParams.Sort()
20+
21+
stringToSign := strings.ToUpper(method) + "&%2F&" +
22+
url.QueryEscape(strings.Join(sortedParams, "&"))
23+
24+
key := []byte(accessKeySecret + "&")
25+
hmac := hmac.New(sha1.New, key)
26+
_, _ = hmac.Write([]byte(stringToSign))
27+
signedBytes := hmac.Sum(nil)
28+
signature := base64.StdEncoding.EncodeToString(signedBytes)
29+
urlValues.Set("Signature", signature)
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package aliyun
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/binary"
6+
"fmt"
7+
"net/url"
8+
"time"
9+
)
10+
11+
func newURLValues(accessKeyID string) (values url.Values) {
12+
randBytes := make([]byte, 8) //nolint:gomnd
13+
_, _ = rand.Read(randBytes)
14+
randInt64 := int64(binary.BigEndian.Uint64(randBytes))
15+
16+
values = make(url.Values)
17+
values.Set("AccessKeyId", accessKeyID)
18+
values.Set("Format", "JSON")
19+
values.Set("Version", "2015-01-09")
20+
values.Set("SignatureMethod", "HMAC-SHA1")
21+
values.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05Z"))
22+
values.Set("SignatureVersion", "1.0")
23+
values.Set("SignatureNonce", fmt.Sprint(randInt64))
24+
return values
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package aliyun
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net"
8+
"net/http"
9+
"net/url"
10+
11+
"github.com/qdm12/ddns-updater/internal/settings/constants"
12+
"github.com/qdm12/ddns-updater/internal/settings/errors"
13+
"github.com/qdm12/ddns-updater/internal/settings/utils"
14+
)
15+
16+
func (p *Provider) createRecord(ctx context.Context,
17+
client *http.Client, ip net.IP) (recordID string, err error) {
18+
recordType := constants.A
19+
if ip.To4() == nil {
20+
recordType = constants.AAAA
21+
}
22+
23+
u := &url.URL{
24+
Scheme: "https",
25+
Host: "alidns.aliyuncs.com",
26+
}
27+
values := newURLValues(p.accessKeyID)
28+
values.Set("Action", "AddDomainRecord")
29+
values.Set("DomainName", p.domain)
30+
values.Set("RR", p.host)
31+
values.Set("Type", recordType)
32+
values.Set("Value", ip.String())
33+
34+
sign(http.MethodGet, values, p.accessSecret)
35+
36+
u.RawQuery = values.Encode()
37+
38+
request, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
39+
if err != nil {
40+
return "", fmt.Errorf("%w: %w", errors.ErrBadRequest, err)
41+
}
42+
43+
response, err := client.Do(request)
44+
if err != nil {
45+
return "", fmt.Errorf("doing HTTP request: %w", err)
46+
}
47+
defer response.Body.Close()
48+
49+
if response.StatusCode != http.StatusOK {
50+
return "", fmt.Errorf("%w: %d: %s",
51+
errors.ErrBadHTTPStatus, response.StatusCode,
52+
utils.BodyToSingleLine(response.Body))
53+
}
54+
55+
var data struct {
56+
RecordID string `json:"RecordId"`
57+
}
58+
decoder := json.NewDecoder(response.Body)
59+
err = decoder.Decode(&data)
60+
if err != nil {
61+
return "", fmt.Errorf("%w: %w", errors.ErrUnmarshalResponse, err)
62+
}
63+
64+
return data.RecordID, nil
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package aliyun
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"net/url"
10+
11+
"github.com/qdm12/ddns-updater/internal/settings/errors"
12+
"github.com/qdm12/ddns-updater/internal/settings/utils"
13+
)
14+
15+
func (p *Provider) getRecordID(ctx context.Context, client *http.Client,
16+
recordType string) (recordID string, err error) {
17+
u := &url.URL{
18+
Scheme: "https",
19+
Host: "dns.aliyuncs.com",
20+
}
21+
values := newURLValues(p.accessKeyID)
22+
values.Set("Action", "DescribeDomainRecords")
23+
values.Set("DomainName", p.domain)
24+
values.Set("RRKeyWord", p.host)
25+
values.Set("Type", recordType)
26+
27+
sign(http.MethodGet, values, p.accessSecret)
28+
29+
u.RawQuery = values.Encode()
30+
31+
request, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
32+
if err != nil {
33+
return "", fmt.Errorf("%w: %w", errors.ErrBadRequest, err)
34+
}
35+
36+
response, err := client.Do(request)
37+
if err != nil {
38+
return "", err
39+
}
40+
defer response.Body.Close()
41+
42+
switch response.StatusCode {
43+
case http.StatusOK:
44+
case http.StatusNotFound:
45+
return "", fmt.Errorf("%w", errors.ErrRecordNotFound)
46+
case http.StatusBadRequest:
47+
bodyBytes, err := io.ReadAll(response.Body)
48+
if err != nil {
49+
return "", fmt.Errorf("reading response body: %w", err)
50+
}
51+
52+
var data struct {
53+
Code string `json:"Code"`
54+
}
55+
err = json.Unmarshal(bodyBytes, &data)
56+
if err != nil || data.Code != "InvalidDomainName.NoExist" {
57+
return "", fmt.Errorf("%w: %d: %s",
58+
errors.ErrBadHTTPStatus, response.StatusCode,
59+
utils.BodyToSingleLine(response.Body))
60+
}
61+
62+
return "", fmt.Errorf("%w", errors.ErrRecordNotFound)
63+
default:
64+
return "", fmt.Errorf("%w: %d: %s",
65+
errors.ErrBadHTTPStatus, response.StatusCode,
66+
utils.BodyToSingleLine(response.Body))
67+
}
68+
69+
decoder := json.NewDecoder(response.Body)
70+
var data struct {
71+
DomainRecords struct {
72+
Record []struct {
73+
RecordID string `json:"RecordId"`
74+
}
75+
}
76+
}
77+
err = decoder.Decode(&data)
78+
if err != nil {
79+
return "", fmt.Errorf("%w: %w", errors.ErrUnmarshalResponse, err)
80+
}
81+
82+
switch len(data.DomainRecords.Record) {
83+
case 0:
84+
return "", fmt.Errorf("%w", errors.ErrRecordNotFound)
85+
case 1:
86+
default:
87+
return "", fmt.Errorf("%w: %d records found instead of 1",
88+
errors.ErrNumberOfResultsReceived, len(data.DomainRecords.Record))
89+
}
90+
91+
return data.DomainRecords.Record[0].RecordID, nil
92+
}

0 commit comments

Comments
 (0)