GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 09e2c6...a4f7a0 )
by
unknown
05:49
created

r.WithStsEndpoint   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
package providers
2
3
import (
4
	"encoding/json"
5
	"errors"
6
	"fmt"
7
	"io/ioutil"
8
	"net/http"
9
	"net/url"
10
	"strconv"
11
	"strings"
12
	"time"
13
14
	"github.com/aliyun/credentials-go/credentials/internal/utils"
15
)
16
17
type assumedRoleUser struct {
18
}
19
20
type credentials struct {
21
	SecurityToken   *string `json:"SecurityToken"`
22
	Expiration      *string `json:"Expiration"`
23
	AccessKeySecret *string `json:"AccessKeySecret"`
24
	AccessKeyId     *string `json:"AccessKeyId"`
25
}
26
27
type assumeRoleResponse struct {
28
	RequestID       *string          `json:"RequestId"`
29
	AssumedRoleUser *assumedRoleUser `json:"AssumedRoleUser"`
30
	Credentials     *credentials     `json:"Credentials"`
31
}
32
33
type sessionCredentials struct {
34
	AccessKeyId     string
35
	AccessKeySecret string
36
	SecurityToken   string
37
	Expiration      string
38
}
39
40
type HttpOptions struct {
41
	Proxy          string
42
	ConnectTimeout int
43
	ReadTimeout    int
44
}
45
46
type RAMRoleARNCredentialsProvider struct {
47
	credentialsProvider CredentialsProvider
48
	roleArn             string
49
	roleSessionName     string
50
	durationSeconds     int
51
	policy              string
52
	externalId          string
53
	// for sts endpoint
54
	stsRegionId string
55
	stsEndpoint string
56
	// for http options
57
	httpOptions *HttpOptions
58
	// inner
59
	expirationTimestamp int64
60
	lastUpdateTimestamp int64
61
	sessionCredentials  *sessionCredentials
62
}
63
64
type RAMRoleARNCredentialsProviderBuilder struct {
65
	provider *RAMRoleARNCredentialsProvider
66
}
67
68
func NewRAMRoleARNCredentialsProviderBuilder() *RAMRoleARNCredentialsProviderBuilder {
69
	return &RAMRoleARNCredentialsProviderBuilder{
70
		provider: &RAMRoleARNCredentialsProvider{},
71
	}
72
}
73
74
func (builder *RAMRoleARNCredentialsProviderBuilder) WithCredentialsProvider(credentialsProvider CredentialsProvider) *RAMRoleARNCredentialsProviderBuilder {
75
	builder.provider.credentialsProvider = credentialsProvider
76
	return builder
77
}
78
79
func (builder *RAMRoleARNCredentialsProviderBuilder) WithRoleArn(roleArn string) *RAMRoleARNCredentialsProviderBuilder {
80
	builder.provider.roleArn = roleArn
81
	return builder
82
}
83
84
func (builder *RAMRoleARNCredentialsProviderBuilder) WithStsRegionId(regionId string) *RAMRoleARNCredentialsProviderBuilder {
85
	builder.provider.stsRegionId = regionId
86
	return builder
87
}
88
89
func (builder *RAMRoleARNCredentialsProviderBuilder) WithStsEndpoint(endpoint string) *RAMRoleARNCredentialsProviderBuilder {
90
	builder.provider.stsEndpoint = endpoint
91
	return builder
92
}
93
94
func (builder *RAMRoleARNCredentialsProviderBuilder) WithRoleSessionName(roleSessionName string) *RAMRoleARNCredentialsProviderBuilder {
95
	builder.provider.roleSessionName = roleSessionName
96
	return builder
97
}
98
99
func (builder *RAMRoleARNCredentialsProviderBuilder) WithPolicy(policy string) *RAMRoleARNCredentialsProviderBuilder {
100
	builder.provider.policy = policy
101
	return builder
102
}
103
104
func (builder *RAMRoleARNCredentialsProviderBuilder) WithExternalId(externalId string) *RAMRoleARNCredentialsProviderBuilder {
105
	builder.provider.externalId = externalId
106
	return builder
107
}
108
109
func (builder *RAMRoleARNCredentialsProviderBuilder) WithDurationSeconds(durationSeconds int) *RAMRoleARNCredentialsProviderBuilder {
110
	builder.provider.durationSeconds = durationSeconds
111
	return builder
112
}
113
114
func (builder *RAMRoleARNCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *RAMRoleARNCredentialsProviderBuilder {
115
	builder.provider.httpOptions = httpOptions
116
	return builder
117
}
118
119
func (builder *RAMRoleARNCredentialsProviderBuilder) Build() (provider *RAMRoleARNCredentialsProvider, err error) {
120
	if builder.provider.credentialsProvider == nil {
121
		err = errors.New("must specify a previous credentials provider to asssume role")
122
		return
123
	}
124
125
	if builder.provider.roleArn == "" {
126
		err = errors.New("the RoleArn is empty")
127
		return
128
	}
129
130
	if builder.provider.roleSessionName == "" {
131
		builder.provider.roleSessionName = "credentials-go-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10)
132
	}
133
134
	// duration seconds
135
	if builder.provider.durationSeconds == 0 {
136
		// default to 3600
137
		builder.provider.durationSeconds = 3600
138
	}
139
140
	if builder.provider.durationSeconds < 900 {
141
		err = errors.New("session duration should be in the range of 900s - max session duration")
142
		return
143
	}
144
145
	// sts endpoint
146
	if builder.provider.stsEndpoint == "" {
147
		if builder.provider.stsRegionId != "" {
148
			builder.provider.stsEndpoint = fmt.Sprintf("sts.%s.aliyuncs.com", builder.provider.stsRegionId)
149
		} else {
150
			builder.provider.stsEndpoint = "sts.aliyuncs.com"
151
		}
152
	}
153
154
	provider = builder.provider
155
	return
156
}
157
158
func (provider *RAMRoleARNCredentialsProvider) getCredentials(cc *Credentials) (session *sessionCredentials, err error) {
159
	method := "POST"
160
	host := provider.stsEndpoint
161
	queries := make(map[string]string)
162
	queries["Version"] = "2015-04-01"
163
	queries["Action"] = "AssumeRole"
164
	queries["Format"] = "JSON"
165
	queries["Timestamp"] = utils.GetTimeInFormatISO8601()
166
	queries["SignatureMethod"] = "HMAC-SHA1"
167
	queries["SignatureVersion"] = "1.0"
168
	queries["SignatureNonce"] = utils.GetNonce()
169
	queries["AccessKeyId"] = cc.AccessKeyId
170
	if cc.SecurityToken != "" {
171
		queries["SecurityToken"] = cc.SecurityToken
172
	}
173
174
	bodyForm := make(map[string]string)
175
	bodyForm["RoleArn"] = provider.roleArn
176
	if provider.policy != "" {
177
		bodyForm["Policy"] = provider.policy
178
	}
179
	if provider.externalId != "" {
180
		bodyForm["ExternalId"] = provider.externalId
181
	}
182
	bodyForm["RoleSessionName"] = provider.roleSessionName
183
	bodyForm["DurationSeconds"] = strconv.Itoa(provider.durationSeconds)
184
185
	// caculate signature
186
	signParams := make(map[string]string)
187
	for key, value := range queries {
188
		signParams[key] = value
189
	}
190
	for key, value := range bodyForm {
191
		signParams[key] = value
192
	}
193
194
	stringToSign := utils.GetURLFormedMap(signParams)
195
	stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
196
	stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
197
	stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
198
	stringToSign = url.QueryEscape(stringToSign)
199
	stringToSign = method + "&%2F&" + stringToSign
200
	secret := cc.AccessKeySecret + "&"
201
	queries["Signature"] = utils.ShaHmac1(stringToSign, secret)
202
203
	querystring := utils.GetURLFormedMap(queries)
204
	// do request
205
	httpUrl := fmt.Sprintf("https://%s/?%s", host, querystring)
206
207
	body := utils.GetURLFormedMap(bodyForm)
208
209
	httpRequest, err := hookNewRequest(http.NewRequest)(method, httpUrl, strings.NewReader(body))
210
	if err != nil {
211
		return
212
	}
213
214
	// set headers
215
	httpRequest.Header["Accept-Encoding"] = []string{"identity"}
216
	httpRequest.Header["Content-Type"] = []string{"application/x-www-form-urlencoded"}
217
	httpRequest.Header["x-credentials-provider"] = []string{cc.ProviderName}
218
	httpClient := &http.Client{}
219
220
	if provider.httpOptions != nil {
221
		httpClient.Timeout = time.Duration(provider.httpOptions.ReadTimeout) * time.Second
222
		proxy := &url.URL{}
223
		if provider.httpOptions.Proxy != "" {
224
			proxy, err = url.Parse(provider.httpOptions.Proxy)
225
			if err != nil {
226
				return
227
			}
228
		}
229
		trans := &http.Transport{}
230
		if proxy != nil && provider.httpOptions.Proxy != "" {
231
			trans.Proxy = http.ProxyURL(proxy)
232
		}
233
		trans.DialContext = utils.Timeout(time.Duration(provider.httpOptions.ConnectTimeout) * time.Second)
234
		httpClient.Transport = trans
235
	}
236
237
	httpResponse, err := hookDo(httpClient.Do)(httpRequest)
238
	if err != nil {
239
		return
240
	}
241
242
	defer httpResponse.Body.Close()
243
244
	responseBody, err := ioutil.ReadAll(httpResponse.Body)
245
	if err != nil {
246
		return
247
	}
248
249
	if httpResponse.StatusCode != http.StatusOK {
250
		err = errors.New("refresh session token failed: " + string(responseBody))
251
		return
252
	}
253
	var data assumeRoleResponse
254
	err = json.Unmarshal(responseBody, &data)
255
	if err != nil {
256
		err = fmt.Errorf("refresh RoleArn sts token err, json.Unmarshal fail: %s", err.Error())
257
		return
258
	}
259
	if data.Credentials == nil {
260
		err = fmt.Errorf("refresh RoleArn sts token err, fail to get credentials")
261
		return
262
	}
263
264
	if data.Credentials.AccessKeyId == nil || data.Credentials.AccessKeySecret == nil || data.Credentials.SecurityToken == nil {
265
		err = fmt.Errorf("refresh RoleArn sts token err, fail to get credentials")
266
		return
267
	}
268
269
	session = &sessionCredentials{
270
		AccessKeyId:     *data.Credentials.AccessKeyId,
271
		AccessKeySecret: *data.Credentials.AccessKeySecret,
272
		SecurityToken:   *data.Credentials.SecurityToken,
273
		Expiration:      *data.Credentials.Expiration,
274
	}
275
	return
276
}
277
278
func (provider *RAMRoleARNCredentialsProvider) needUpdateCredential() (result bool) {
279
	if provider.expirationTimestamp == 0 {
280
		return true
281
	}
282
283
	return provider.expirationTimestamp-time.Now().Unix() <= 180
284
}
285
286
func (provider *RAMRoleARNCredentialsProvider) GetCredentials() (cc *Credentials, err error) {
287
	if provider.sessionCredentials == nil || provider.needUpdateCredential() {
288
		// 获取前置凭证
289
		previousCredentials, err1 := provider.credentialsProvider.GetCredentials()
290
		if err1 != nil {
291
			return nil, err1
292
		}
293
		sessionCredentials, err2 := provider.getCredentials(previousCredentials)
294
		if err2 != nil {
295
			return nil, err2
296
		}
297
298
		expirationTime, err := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration)
299
		if err != nil {
300
			return nil, err
301
		}
302
303
		provider.expirationTimestamp = expirationTime.Unix()
304
		provider.lastUpdateTimestamp = time.Now().Unix()
305
		provider.sessionCredentials = sessionCredentials
306
	}
307
308
	cc = &Credentials{
309
		AccessKeyId:     provider.sessionCredentials.AccessKeyId,
310
		AccessKeySecret: provider.sessionCredentials.AccessKeySecret,
311
		SecurityToken:   provider.sessionCredentials.SecurityToken,
312
		ProviderName:    fmt.Sprintf("%s/%s", provider.GetProviderName(), provider.credentialsProvider.GetProviderName()),
313
	}
314
	return
315
}
316
317
func (provider *RAMRoleARNCredentialsProvider) GetProviderName() string {
318
	return "ram_role_arn"
319
}
320