-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathremote-provider.go
96 lines (86 loc) · 2.11 KB
/
remote-provider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//go:build remote
// +build remote
package daemon
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"io"
"log/slog"
"net/http"
"net/url"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
func padding(src []byte, blockSize int) []byte {
p := blockSize - len(src)%blockSize
return append(src, bytes.Repeat([]byte{byte(p)}, p)...)
}
func unpadding(src []byte) []byte {
l := len(src)
if n := int(src[l-1]); n <= l {
return src[:l-n]
}
return src
}
// 解密
func decrypt(data, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
buf := make([]byte, len(data))
cipher.NewCBCDecrypter(block, iv).CryptBlocks(buf, data)
return unpadding(buf), nil
}
type RemoteProvider struct {
viper.RemoteProvider
EncryptSecret []byte
TargetURL string
logger *slog.Logger
}
func (c *RemoteProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
c.RemoteProvider = rp
if c.TargetURL == "" {
target, err := url.Parse(rp.Endpoint())
if err != nil {
return nil, err
}
if target.Host == "" {
target.Host = defaultRemoteEndpoint
}
if target.Scheme == "" {
target.Scheme = "https"
}
target.Path = rp.Path()
c.TargetURL = target.String()
}
// Get remote config
rsp, err := http.Post(c.TargetURL, "application/object-stream", bytes.NewBuffer(c.EncryptSecret))
if err != nil {
c.logger.Error("Failed to request remote", "err", err.Error())
return nil, err
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, errors.Errorf("Failed to get remote config: %s", rsp.Status)
}
buf, err := io.ReadAll(rsp.Body)
if err != nil {
return nil, err
}
if len(buf) < aes.BlockSize {
return nil, errors.New("invalid remote config")
}
buf, err = decrypt(buf[aes.BlockSize:], []byte(rp.SecretKeyring()), buf[:aes.BlockSize])
if err != nil {
return nil, err
}
return bytes.NewReader(buf), nil
}
func (c *RemoteProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
panic("unimplemented")
}
func (c *RemoteProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
panic("unimplemented")
}