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 ( b5116a...3bd38f )
by
unknown
05:35
created

edentials   D

Complexity

Conditions 12

Size

Total Lines 62
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 43
nop 0
dl 0
loc 62
rs 4.8
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like providers.*ECSRAMRoleCredentialsProvider.getCredentials often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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