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 ( e68691...412f4e )
by Jackson
06:39
created

r.Build   A

Complexity

Conditions 5

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nop 0
dl 0
loc 22
rs 9.2833
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
	"os"
10
	"strconv"
11
	"strings"
12
	"time"
13
14
	"github.com/aliyun/credentials-go/credentials/internal/utils"
15
	"github.com/aliyun/credentials-go/credentials/request"
16
)
17
18
const securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
19
const apiTokenURL = "http://100.100.100.200/latest/api/token"
20
21
type ECSRAMRoleCredentialsProvider struct {
22
	roleName                     string
23
	metadataTokenDurationSeconds int
24
	enableIMDSv2                 bool
25
	runtime                      *utils.Runtime
26
	// for sts
27
	session             *sessionCredentials
28
	expirationTimestamp int64
29
}
30
31
type ECSRAMRoleCredentialsProviderBuilder struct {
32
	provider *ECSRAMRoleCredentialsProvider
33
}
34
35
func NewECSRAMRoleCredentialsProviderBuilder() *ECSRAMRoleCredentialsProviderBuilder {
36
	return &ECSRAMRoleCredentialsProviderBuilder{
37
		provider: &ECSRAMRoleCredentialsProvider{
38
			// TBD: 默认启用 IMDS v2
39
			// enableIMDSv2: os.Getenv("ALIBABA_CLOUD_IMDSV2_DISABLED") != "true", // 默认启用 v2
40
		},
41
	}
42
}
43
44
func (builder *ECSRAMRoleCredentialsProviderBuilder) WithMetadataTokenDurationSeconds(metadataTokenDurationSeconds int) *ECSRAMRoleCredentialsProviderBuilder {
45
	builder.provider.metadataTokenDurationSeconds = metadataTokenDurationSeconds
46
	return builder
47
}
48
49
func (builder *ECSRAMRoleCredentialsProviderBuilder) WithRoleName(roleName string) *ECSRAMRoleCredentialsProviderBuilder {
50
	builder.provider.roleName = roleName
51
	return builder
52
}
53
54
func (builder *ECSRAMRoleCredentialsProviderBuilder) WithEnableIMDSv2(enableIMDSv2 bool) *ECSRAMRoleCredentialsProviderBuilder {
55
	builder.provider.enableIMDSv2 = enableIMDSv2
56
	return builder
57
}
58
59
const defaultMetadataTokenDuration = 21600 // 6 hours
60
61
func (builder *ECSRAMRoleCredentialsProviderBuilder) Build() (provider *ECSRAMRoleCredentialsProvider, err error) {
62
	// 设置 roleName 默认值
63
	if builder.provider.roleName == "" {
64
		builder.provider.roleName = os.Getenv("ALIBABA_CLOUD_ECS_METADATA")
65
	}
66
67
	if builder.provider.metadataTokenDurationSeconds == 0 {
68
		builder.provider.metadataTokenDurationSeconds = defaultMetadataTokenDuration
69
	}
70
71
	if builder.provider.metadataTokenDurationSeconds < 1 || builder.provider.metadataTokenDurationSeconds > 21600 {
72
		err = errors.New("the metadata token duration seconds must be 1-21600")
73
		return
74
	}
75
76
	builder.provider.runtime = &utils.Runtime{
77
		ConnectTimeout: 5,
78
		ReadTimeout:    5,
79
	}
80
81
	provider = builder.provider
82
	return
83
}
84
85
type ecsRAMRoleResponse struct {
86
	Code            *string `json:"Code"`
87
	AccessKeyId     *string `json:"AccessKeyId"`
88
	AccessKeySecret *string `json:"AccessKeySecret"`
89
	SecurityToken   *string `json:"SecurityToken"`
90
	LastUpdated     *string `json:"LastUpdated"`
91
	Expiration      *string `json:"Expiration"`
92
}
93
94
func (provider *ECSRAMRoleCredentialsProvider) needUpdateCredential() bool {
95
	if provider.expirationTimestamp == 0 {
96
		return true
97
	}
98
99
	return provider.expirationTimestamp-time.Now().Unix() <= 180
100
}
101
102
func (provider *ECSRAMRoleCredentialsProvider) getRoleName() (roleName string, err error) {
103
	httpRequest, err := hookNewRequest(http.NewRequest)("GET", securityCredURL, strings.NewReader(""))
104
	if err != nil {
105
		err = fmt.Errorf("get role name failed: %s", err.Error())
106
		return
107
	}
108
109
	if provider.enableIMDSv2 {
110
		metadataToken, err := provider.getMetadataToken()
111
		if err != nil {
112
			return "", err
113
		}
114
		httpRequest.Header.Set("x-aliyun-ecs-metadata-token", metadataToken)
115
	}
116
117
	httpClient := &http.Client{
118
		Timeout: 5 * time.Second,
119
	}
120
	httpResponse, err := hookDo(httpClient.Do)(httpRequest)
121
	if err != nil {
122
		err = fmt.Errorf("get role name failed: %s", err.Error())
123
		return
124
	}
125
126
	if httpResponse.StatusCode != http.StatusOK {
127
		err = fmt.Errorf("get role name failed: request %s %d", securityCredURL, httpResponse.StatusCode)
128
		return
129
	}
130
131
	defer httpResponse.Body.Close()
132
133
	responseBody, err := ioutil.ReadAll(httpResponse.Body)
134
	if err != nil {
135
		return
136
	}
137
138
	roleName = strings.TrimSpace(string(responseBody))
139
	return
140
}
141
142
func (provider *ECSRAMRoleCredentialsProvider) getCredentials() (session *sessionCredentials, err error) {
143
	roleName := provider.roleName
144
	if roleName == "" {
145
		roleName, err = provider.getRoleName()
146
		if err != nil {
147
			return
148
		}
149
	}
150
151
	requestUrl := securityCredURL + roleName
152
	httpRequest, err := hookNewRequest(http.NewRequest)("GET", requestUrl, strings.NewReader(""))
153
	if err != nil {
154
		err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
155
		return
156
	}
157
158
	if provider.enableIMDSv2 {
159
		metadataToken, err := provider.getMetadataToken()
160
		if err != nil {
161
			return nil, err
162
		}
163
		httpRequest.Header.Set("x-aliyun-ecs-metadata-token", metadataToken)
164
	}
165
166
	httpClient := &http.Client{
167
		Timeout: 5 * time.Second,
168
	}
169
	httpResponse, err := hookDo(httpClient.Do)(httpRequest)
170
	if err != nil {
171
		err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error())
172
		return
173
	}
174
175
	defer httpResponse.Body.Close()
176
177
	responseBody, err := ioutil.ReadAll(httpResponse.Body)
178
	if err != nil {
179
		return
180
	}
181
182
	if httpResponse.StatusCode != http.StatusOK {
183
		err = fmt.Errorf("refresh Ecs sts token err, httpStatus: %d, message = %s", httpResponse.StatusCode, string(responseBody))
184
		return
185
	}
186
187
	var data ecsRAMRoleResponse
188
	err = json.Unmarshal(responseBody, &data)
189
	if err != nil {
190
		err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error())
191
		return
192
	}
193
194
	if data.AccessKeyId == nil || data.AccessKeySecret == nil || data.SecurityToken == nil {
195
		err = fmt.Errorf("refresh Ecs sts token err, fail to get credentials")
196
		return
197
	}
198
199
	if *data.Code != "Success" {
200
		err = fmt.Errorf("refresh Ecs sts token err, Code is not Success")
201
		return
202
	}
203
204
	session = &sessionCredentials{
205
		AccessKeyId:     *data.AccessKeyId,
206
		AccessKeySecret: *data.AccessKeySecret,
207
		SecurityToken:   *data.SecurityToken,
208
		Expiration:      *data.Expiration,
209
	}
210
	return
211
}
212
213
func (provider *ECSRAMRoleCredentialsProvider) GetCredentials() (cc *Credentials, err error) {
214
	if provider.session == nil || provider.needUpdateCredential() {
215
		session, err1 := provider.getCredentials()
216
		if err1 != nil {
217
			return nil, err1
218
		}
219
220
		provider.session = session
221
		expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", session.Expiration)
222
		if err2 != nil {
223
			return nil, err2
224
		}
225
		provider.expirationTimestamp = expirationTime.Unix()
226
	}
227
228
	cc = &Credentials{
229
		AccessKeyId:     provider.session.AccessKeyId,
230
		AccessKeySecret: provider.session.AccessKeySecret,
231
		SecurityToken:   provider.session.SecurityToken,
232
		ProviderName:    provider.GetProviderName(),
233
	}
234
	return
235
}
236
237
func (provider *ECSRAMRoleCredentialsProvider) GetProviderName() string {
238
	return "ecs_ram_role"
239
}
240
241
func (provider *ECSRAMRoleCredentialsProvider) getMetadataToken() (metadataToken string, err error) {
242
	request := request.NewCommonRequest()
243
	request.URL = apiTokenURL
244
	request.Method = "PUT"
245
	request.Headers["X-aliyun-ecs-metadata-token-ttl-seconds"] = strconv.Itoa(provider.metadataTokenDurationSeconds)
246
	content, err := doAction(request, provider.runtime)
247
	if err != nil {
248
		err = fmt.Errorf("get metadata token failed: %s", err.Error())
249
		return
250
	}
251
	metadataToken = string(content)
252
	return
253
}
254