utils.go raw
1 package base
2
3 import (
4 "crypto/md5"
5 "encoding/base64"
6 "encoding/hex"
7 "encoding/json"
8 "fmt"
9 "math/rand"
10 "net/http"
11 "net/url"
12 "reflect"
13 "strconv"
14 "strings"
15 "time"
16
17 "github.com/google/uuid"
18 )
19
20 var (
21 letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
22 defaultRetryTimes uint64 = 2
23 defaultRetryInterval = 1 * time.Second
24 )
25
26 func init() {
27 rand.Seed(time.Now().Unix())
28 }
29
30 func createTempAKSK() (accessKeyId string, plainSk string, err error) {
31 if accessKeyId, err = generateAccessKeyId("AKTP"); err != nil {
32 return
33 }
34
35 plainSk, err = generateSecretKey()
36 if err != nil {
37 return
38 }
39 return
40 }
41
42 func generateAccessKeyId(prefix string) (string, error) {
43 uuid := uuid.New()
44
45 uidBase64 := base64.StdEncoding.EncodeToString([]byte(strings.Replace(uuid.String(), "-", "", -1)))
46
47 s := strings.Replace(uidBase64, "=", "", -1)
48 s = strings.Replace(s, "/", "", -1)
49 s = strings.Replace(s, "+", "", -1)
50 s = strings.Replace(s, "-", "", -1)
51 return prefix + s, nil
52 }
53
54 func randStringRunes(n int) string {
55 b := make([]rune, n)
56 for i := range b {
57 b[i] = letterRunes[rand.Intn(len(letterRunes))]
58 }
59 return string(b)
60 }
61
62 func generateSecretKey() (string, error) {
63 randString32 := randStringRunes(32)
64 return aesEncryptCBCWithBase64([]byte(randString32), []byte("bytedance-isgood"))
65 }
66
67 func createInnerToken(credentials Credentials, sts *SecurityToken2, inlinePolicy *Policy, t int64) (*InnerToken, error) {
68 var err error
69 innerToken := new(InnerToken)
70
71 innerToken.LTAccessKeyId = credentials.AccessKeyID
72 innerToken.AccessKeyId = sts.AccessKeyID
73 innerToken.ExpiredTime = t
74
75 key := md5.Sum([]byte(credentials.SecretAccessKey))
76 innerToken.SignedSecretAccessKey, err = aesEncryptCBCWithBase64([]byte(sts.SecretAccessKey), key[:])
77 if err != nil {
78 return nil, err
79 }
80
81 if inlinePolicy != nil {
82 b, _ := json.Marshal(inlinePolicy)
83 innerToken.PolicyString = string(b)
84 }
85
86 signStr := fmt.Sprintf("%s|%s|%d|%s|%s", innerToken.LTAccessKeyId, innerToken.AccessKeyId, innerToken.ExpiredTime, innerToken.SignedSecretAccessKey, innerToken.PolicyString)
87
88 innerToken.Signature = hex.EncodeToString(hmacSHA256(key[:], signStr))
89 return innerToken, nil
90 }
91
92 func getTimeout(serviceTimeout, apiTimeout, customTimeout time.Duration) time.Duration {
93 timeout := time.Second
94 if serviceTimeout != time.Duration(0) {
95 timeout = serviceTimeout
96 }
97 if apiTimeout != time.Duration(0) {
98 timeout = apiTimeout
99 }
100 if customTimeout != time.Duration(0) {
101 timeout = customTimeout
102 }
103 return timeout
104 }
105
106 func getRetrySetting(serviceRetrySettings, apiRetrySettings *RetrySettings) *RetrySettings {
107 retrySettings := &RetrySettings{
108 AutoRetry: false,
109 RetryTimes: new(uint64),
110 RetryInterval: new(time.Duration),
111 }
112 if !apiRetrySettings.AutoRetry || !serviceRetrySettings.AutoRetry {
113 return retrySettings
114 }
115 retrySettings.AutoRetry = true
116 if serviceRetrySettings.RetryTimes != nil {
117 retrySettings.RetryTimes = serviceRetrySettings.RetryTimes
118 } else if apiRetrySettings.RetryTimes != nil {
119 retrySettings.RetryTimes = apiRetrySettings.RetryTimes
120 } else {
121 retrySettings.RetryTimes = &defaultRetryTimes
122 }
123 if serviceRetrySettings.RetryInterval != nil {
124 retrySettings.RetryInterval = serviceRetrySettings.RetryInterval
125 } else if apiRetrySettings.RetryInterval != nil {
126 retrySettings.RetryInterval = apiRetrySettings.RetryInterval
127 } else {
128 retrySettings.RetryInterval = &defaultRetryInterval
129 }
130 return retrySettings
131 }
132
133 func mergeQuery(query1, query2 url.Values) (query url.Values) {
134 query = url.Values{}
135 if query1 != nil {
136 for k, vv := range query1 {
137 for _, v := range vv {
138 query.Add(k, v)
139 }
140 }
141 }
142
143 if query2 != nil {
144 for k, vv := range query2 {
145 for _, v := range vv {
146 query.Add(k, v)
147 }
148 }
149 }
150 return
151 }
152
153 func mergeHeader(header1, header2 http.Header) (header http.Header) {
154 header = http.Header{}
155 if header1 != nil {
156 for k, v := range header1 {
157 header.Set(k, strings.Join(v, ";"))
158 }
159 }
160 if header2 != nil {
161 for k, v := range header2 {
162 header.Set(k, strings.Join(v, ";"))
163 }
164 }
165
166 return
167 }
168
169 func NewAllowStatement(actions, resources []string) *Statement {
170 sts := new(Statement)
171 sts.Effect = "Allow"
172 sts.Action = actions
173 sts.Resource = resources
174
175 return sts
176 }
177
178 func NewDenyStatement(actions, resources []string) *Statement {
179 sts := new(Statement)
180 sts.Effect = "Deny"
181 sts.Action = actions
182 sts.Resource = resources
183
184 return sts
185 }
186
187 func ToUrlValues(i interface{}) (values url.Values) {
188 values = url.Values{}
189 iVal := reflect.ValueOf(i).Elem()
190 typ := iVal.Type()
191 for i := 0; i < iVal.NumField(); i++ {
192 f := iVal.Field(i)
193 // You ca use tags here...
194 // tag := typ.Field(i).Tag.Get("tagname")
195 // Convert each type into a string for the url.Values string map
196 var v string
197 switch f.Interface().(type) {
198 case int, int8, int16, int32, int64:
199 v = strconv.FormatInt(f.Int(), 10)
200 case uint, uint8, uint16, uint32, uint64:
201 v = strconv.FormatUint(f.Uint(), 10)
202 case float32:
203 v = strconv.FormatFloat(f.Float(), 'f', 4, 32)
204 case float64:
205 v = strconv.FormatFloat(f.Float(), 'f', 4, 64)
206 case []byte:
207 v = string(f.Bytes())
208 case bool:
209 v = strconv.FormatBool(f.Bool())
210 case string:
211 if f.Len() == 0 {
212 continue
213 }
214 v = f.String()
215 }
216 values.Set(typ.Field(i).Name, v)
217 }
218 return
219 }
220
221 func UnmarshalResultInto(data []byte, result interface{}) error {
222 resp := new(CommonResponse)
223 if err := json.Unmarshal(data, resp); err != nil {
224 return fmt.Errorf("fail to unmarshal response, %v", err)
225 }
226 errObj := resp.ResponseMetadata.Error
227 if errObj != nil && errObj.CodeN != 0 {
228 return fmt.Errorf("request %s error %s", resp.ResponseMetadata.RequestId, errObj.Message)
229 }
230
231 data, err := json.Marshal(resp.Result)
232 if err != nil {
233 return fmt.Errorf("fail to marshal result, %v", err)
234 }
235 if err = json.Unmarshal(data, result); err != nil {
236 return fmt.Errorf("fail to unmarshal result, %v", err)
237 }
238 return nil
239 }
240