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 ( b0bdc5...b5116a )
by
unknown
06:34
created

credentials/internal/providers/oidc.go   B

Size/Duplication

Total Lines 285
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 49
eloc 183
dl 0
loc 285
rs 8.48
c 0
b 0
f 0

15 Methods

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