diff --git a/go.mod b/go.mod index 6755d653..2bf1274b 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/alibabacloud-go/ram-20150501 v1.0.2 github.com/alibabacloud-go/sts-20150401 v1.1.0 github.com/alibabacloud-go/tea v1.2.2 - github.com/aliyun/alibaba-cloud-sdk-go v1.62.708 + github.com/aliyun/alibaba-cloud-sdk-go v1.63.56 github.com/aliyun/credentials-go v1.3.2 github.com/briandowns/spinner v1.23.0 github.com/fatih/color v1.18.0 diff --git a/go.sum b/go.sum index 3ecdbcc8..bfa2be25 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eU github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.708 h1:5VYgj4ixzuxrGEKzm6t8TpyjlWeOZPuc6NTngdZ2qD0= -github.com/aliyun/alibaba-cloud-sdk-go v1.62.708/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.56 h1:554QLzzX3Q0IuqoHF8ebO5GoN8bkhLqYsdNWhYW0Xy4= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.56/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= github.com/aliyun/credentials-go v1.3.2 h1:L4WppI9rctC8PdlMgyTkF8bBsy9pyKQEzBD1bHMRl+g= diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/cli_profile_credentials_provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/cli_profile_credentials_provider.go new file mode 100644 index 00000000..a75cfd6a --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/cli_profile_credentials_provider.go @@ -0,0 +1,228 @@ +package credentials + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal" +) + +type CLIProfileCredentialsProvider struct { + profileName string + innerProvider CredentialsProvider +} + +type CLIProfileCredentialsProviderBuilder struct { + provider *CLIProfileCredentialsProvider +} + +func (b *CLIProfileCredentialsProviderBuilder) WithProfileName(profileName string) *CLIProfileCredentialsProviderBuilder { + b.provider.profileName = profileName + return b +} + +func (b *CLIProfileCredentialsProviderBuilder) Build() *CLIProfileCredentialsProvider { + // 优先级: + // 1. 使用显示指定的 profileName + // 2. 使用环境变量(ALIBABA_CLOUD_PROFILE)制定的 profileName + // 3. 使用 CLI 配置中的当前 profileName + if b.provider.profileName == "" { + b.provider.profileName = os.Getenv("ALIBABA_CLOUD_PROFILE") + } + + return b.provider +} + +func NewCLIProfileCredentialsProviderBuilder() *CLIProfileCredentialsProviderBuilder { + return &CLIProfileCredentialsProviderBuilder{ + provider: &CLIProfileCredentialsProvider{}, + } +} + +type profile struct { + Name string `json:"name"` + Mode string `json:"mode"` + AccessKeyID string `json:"access_key_id"` + AccessKeySecret string `json:"access_key_secret"` + RegionID string `json:"region_id"` + RoleArn string `json:"ram_role_arn"` + RoleSessionName string `json:"ram_session_name"` + DurationSeconds int `json:"expired_seconds"` + StsRegion string `json:"sts_region"` + EnableVpc bool `json:"enable_vpc"` + SourceProfile string `json:"source_profile"` + RoleName string `json:"ram_role_name"` + OIDCTokenFile string `json:"oidc_token_file"` + OIDCProviderARN string `json:"oidc_provider_arn"` + Policy string `json:"policy"` + ExternalId string `json:"external_id"` +} + +type configuration struct { + Current string `json:"current"` + Profiles []*profile `json:"profiles"` +} + +func newConfigurationFromPath(cfgPath string) (conf *configuration, err error) { + bytes, err := ioutil.ReadFile(cfgPath) + if err != nil { + err = fmt.Errorf("reading aliyun cli config from '%s' failed %v", cfgPath, err) + return + } + + conf = &configuration{} + + err = json.Unmarshal(bytes, conf) + if err != nil { + err = fmt.Errorf("unmarshal aliyun cli config from '%s' failed: %s", cfgPath, string(bytes)) + return + } + + if conf.Profiles == nil || len(conf.Profiles) == 0 { + err = fmt.Errorf("no any configured profiles in '%s'", cfgPath) + return + } + + return +} + +func (conf *configuration) getProfile(name string) (profile *profile, err error) { + for _, p := range conf.Profiles { + if p.Name == name { + profile = p + return + } + } + + err = fmt.Errorf("unable to get profile with '%s'", name) + return +} + +func (provider *CLIProfileCredentialsProvider) getCredentialsProvider(conf *configuration, profileName string) (credentialsProvider CredentialsProvider, err error) { + p, err := conf.getProfile(profileName) + if err != nil { + return + } + + switch p.Mode { + case "AK": + credentialsProvider, err = NewStaticAKCredentialsProviderBuilder(). + WithAccessKeyId(p.AccessKeyID). + WithAccessKeySecret(p.AccessKeySecret). + Build() + case "RamRoleArn": + previousProvider, err1 := NewStaticAKCredentialsProviderBuilder(). + WithAccessKeyId(p.AccessKeyID). + WithAccessKeySecret(p.AccessKeySecret). + Build() + if err1 != nil { + return nil, err1 + } + + credentialsProvider, err = NewRAMRoleARNCredentialsProviderBuilder(). + WithCredentialsProvider(previousProvider). + WithRoleArn(p.RoleArn). + WithRoleSessionName(p.RoleSessionName). + WithDurationSeconds(p.DurationSeconds). + WithStsRegion(p.StsRegion). + WithEnableVpc(p.EnableVpc). + WithPolicy(p.Policy). + WithExternalId(p.ExternalId). + Build() + case "EcsRamRole": + credentialsProvider, err = NewECSRAMRoleCredentialsProviderBuilder().WithRoleName(p.RoleName).Build() + case "OIDC": + credentialsProvider, err = NewOIDCCredentialsProviderBuilder(). + WithOIDCTokenFilePath(p.OIDCTokenFile). + WithOIDCProviderARN(p.OIDCProviderARN). + WithRoleArn(p.RoleArn). + WithStsRegion(p.StsRegion). + WithEnableVpc(p.EnableVpc). + WithDurationSeconds(p.DurationSeconds). + WithRoleSessionName(p.RoleSessionName). + WithPolicy(p.Policy). + Build() + case "ChainableRamRoleArn": + var previousProvider CredentialsProvider + previousProvider, err1 := provider.getCredentialsProvider(conf, p.SourceProfile) + if err1 != nil { + err = fmt.Errorf("get source profile failed: %s", err1.Error()) + return + } + credentialsProvider, err = NewRAMRoleARNCredentialsProviderBuilder(). + WithCredentialsProvider(previousProvider). + WithRoleArn(p.RoleArn). + WithRoleSessionName(p.RoleSessionName). + WithDurationSeconds(p.DurationSeconds). + WithStsRegion(p.StsRegion). + WithEnableVpc(p.EnableVpc). + WithPolicy(p.Policy). + WithExternalId(p.ExternalId). + Build() + default: + err = fmt.Errorf("unsupported profile mode '%s'", p.Mode) + } + + return +} + +// 默认设置为 GetHomePath,测试时便于 mock +var getHomePath = internal.GetHomePath + +func (provider *CLIProfileCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if strings.ToLower(os.Getenv("ALIBABA_CLOUD_CLI_PROFILE_DISABLED")) == "true" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The CLI profile is disabled", nil) + return + } + if provider.innerProvider == nil { + homedir := getHomePath() + if homedir == "" { + err = fmt.Errorf("cannot found home dir") + return + } + + cfgPath := path.Join(homedir, ".aliyun/config.json") + var conf *configuration + conf, err = newConfigurationFromPath(cfgPath) + if err != nil { + return + } + + if provider.profileName == "" { + provider.profileName = conf.Current + } + + provider.innerProvider, err = provider.getCredentialsProvider(conf, provider.profileName) + if err != nil { + return + } + } + + innerCC, err := provider.innerProvider.GetCredentials() + if err != nil { + return + } + + providerName := innerCC.ProviderName + if providerName == "" { + providerName = provider.innerProvider.GetProviderName() + } + + cc = &Credentials{ + AccessKeyId: innerCC.AccessKeyId, + AccessKeySecret: innerCC.AccessKeySecret, + SecurityToken: innerCC.SecurityToken, + ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), providerName), + } + + return +} + +func (provider *CLIProfileCredentialsProvider) GetProviderName() string { + return "cli_profile" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/credentials.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/credentials.go new file mode 100644 index 00000000..09b9905b --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/credentials.go @@ -0,0 +1,1426 @@ +package credentials + +import ( + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "strconv" + "strings" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" +) + +type assumedRoleUser struct { +} + +type credentials struct { + SecurityToken *string `json:"SecurityToken"` + Expiration *string `json:"Expiration"` + AccessKeySecret *string `json:"AccessKeySecret"` + AccessKeyId *string `json:"AccessKeyId"` +} + +type ecsRAMRoleCredentials struct { + SecurityToken *string `json:"SecurityToken"` + Expiration *string `json:"Expiration"` + AccessKeySecret *string `json:"AccessKeySecret"` + AccessKeyId *string `json:"AccessKeyId"` + LastUpdated *string `json:"LastUpdated"` + Code *string `json:"Code"` +} + +type assumeRoleResponse struct { + RequestID *string `json:"RequestId"` + AssumedRoleUser *assumedRoleUser `json:"AssumedRoleUser"` + Credentials *credentials `json:"Credentials"` +} + +type generateSessionAccessKeyResponse struct { + RequestID *string `json:"RequestId"` + SessionAccessKey *sessionAccessKey `json:"SessionAccessKey"` +} + +type sessionAccessKey struct { + SessionAccessKeyId *string `json:"SessionAccessKeyId"` + SessionAccessKeySecret *string `json:"SessionAccessKeySecret"` + Expiration *string `json:"Expiration"` +} + +type SessionCredentials struct { + AccessKeyId string + AccessKeySecret string + SecurityToken string + Expiration string +} + +type Credentials struct { + AccessKeyId string + AccessKeySecret string + SecurityToken string + BearerToken string + ProviderName string +} + +type do func(req *http.Request) (*http.Response, error) + +var hookDo = func(fn do) do { + return fn +} + +type newReuqest func(method, url string, body io.Reader) (*http.Request, error) + +var hookNewRequest = func(fn newReuqest) newReuqest { + return fn +} + +type HttpOptions struct { + // Connection timeout + ConnectTimeout time.Duration + // Read timeout + ReadTimeout time.Duration +} + +type CredentialsProvider interface { + GetCredentials() (cc *Credentials, err error) + GetProviderName() string +} + +type StaticAKCredentialsProvider struct { + accessKeyId string + accessKeySecret string +} + +type StaticAKCredentialsProviderBuilder struct { + provider *StaticAKCredentialsProvider +} + +func NewStaticAKCredentialsProviderBuilder() *StaticAKCredentialsProviderBuilder { + return &StaticAKCredentialsProviderBuilder{ + provider: &StaticAKCredentialsProvider{}, + } +} + +func (builder *StaticAKCredentialsProviderBuilder) WithAccessKeyId(accessKeyId string) *StaticAKCredentialsProviderBuilder { + builder.provider.accessKeyId = accessKeyId + return builder +} + +func (builder *StaticAKCredentialsProviderBuilder) WithAccessKeySecret(accessKeySecret string) *StaticAKCredentialsProviderBuilder { + builder.provider.accessKeySecret = accessKeySecret + return builder +} + +func (builder *StaticAKCredentialsProviderBuilder) Build() (provider *StaticAKCredentialsProvider, err error) { + if builder.provider.accessKeyId == "" { + builder.provider.accessKeyId = os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID") + } + + if builder.provider.accessKeyId == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The access key id is empty", nil) + return + } + + if builder.provider.accessKeySecret == "" { + builder.provider.accessKeySecret = os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET") + } + + if builder.provider.accessKeySecret == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The access key secret is empty", nil) + return + } + + provider = builder.provider + return +} + +func NewStaticAKCredentialsProvider(accessKeyId, accessKeySecret string) *StaticAKCredentialsProvider { + return &StaticAKCredentialsProvider{ + accessKeyId: accessKeyId, + accessKeySecret: accessKeySecret, + } +} + +func (provider *StaticAKCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + cc = &Credentials{ + AccessKeyId: provider.accessKeyId, + AccessKeySecret: provider.accessKeySecret, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *StaticAKCredentialsProvider) GetProviderName() string { + return "static_ak" +} + +type StaticSTSCredentialsProvider struct { + accessKeyId string + accessKeySecret string + securityToken string +} + +type StaticSTSCredentialsProviderBuilder struct { + provider *StaticSTSCredentialsProvider +} + +func NewStaticSTSCredentialsProviderBuilder() *StaticSTSCredentialsProviderBuilder { + return &StaticSTSCredentialsProviderBuilder{ + provider: &StaticSTSCredentialsProvider{}, + } +} + +func (builder *StaticSTSCredentialsProviderBuilder) WithAccessKeyId(accessKeyId string) *StaticSTSCredentialsProviderBuilder { + builder.provider.accessKeyId = accessKeyId + return builder +} + +func (builder *StaticSTSCredentialsProviderBuilder) WithAccessKeySecret(accessKeySecret string) *StaticSTSCredentialsProviderBuilder { + builder.provider.accessKeySecret = accessKeySecret + return builder +} + +func (builder *StaticSTSCredentialsProviderBuilder) WithSecurityToken(securityToken string) *StaticSTSCredentialsProviderBuilder { + builder.provider.securityToken = securityToken + return builder +} + +func (builder *StaticSTSCredentialsProviderBuilder) Build() (provider *StaticSTSCredentialsProvider, err error) { + if builder.provider.accessKeyId == "" { + builder.provider.accessKeyId = os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID") + } + + if builder.provider.accessKeyId == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The access key id is empty", nil) + return + } + + if builder.provider.accessKeySecret == "" { + builder.provider.accessKeySecret = os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET") + } + + if builder.provider.accessKeySecret == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The access key secret is empty", nil) + return + } + + if builder.provider.securityToken == "" { + builder.provider.securityToken = os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN") + } + + if builder.provider.securityToken == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The security token is empty", nil) + return + } + + provider = builder.provider + return +} + +func NewStaticSTSCredentialsProvider(accessKeyId, accessKeySecret, securityToken string) *StaticSTSCredentialsProvider { + return &StaticSTSCredentialsProvider{ + accessKeyId: accessKeyId, + accessKeySecret: accessKeySecret, + securityToken: securityToken, + } +} + +func (provider *StaticSTSCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + cc = &Credentials{ + AccessKeyId: provider.accessKeyId, + AccessKeySecret: provider.accessKeySecret, + SecurityToken: provider.securityToken, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *StaticSTSCredentialsProvider) GetProviderName() string { + return "static_sts" +} + +type BearerTokenCredentialsProvider struct { + bearerToken string +} + +func NewBearerTokenCredentialsProvider(bearerToken string) *BearerTokenCredentialsProvider { + return &BearerTokenCredentialsProvider{ + bearerToken: bearerToken, + } +} + +func (provider *BearerTokenCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + cc = &Credentials{ + BearerToken: provider.bearerToken, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *BearerTokenCredentialsProvider) GetProviderName() string { + return "bearer_token" +} + +// Deprecated: the RSA key pair credentials is deprecated +type RSAKeyPairCredentialsProvider struct { + PublicKeyId string + PrivateKeyId string + durationSeconds int + sessionAccessKey *sessionAccessKey + lastUpdateTimestamp int64 + expirationTimestamp int64 +} + +// Deprecated: the RSA key pair credentials is deprecated +func NewRSAKeyPairCredentialsProvider(publicKeyId, privateKeyId string, durationSeconds int) (provider *RSAKeyPairCredentialsProvider, err error) { + provider = &RSAKeyPairCredentialsProvider{ + PublicKeyId: publicKeyId, + PrivateKeyId: privateKeyId, + } + + if durationSeconds > 0 { + if durationSeconds >= 900 && durationSeconds <= 3600 { + provider.durationSeconds = durationSeconds + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Key Pair session duration should be in the range of 15min - 1hr", nil) + } + } else { + // set to default value + provider.durationSeconds = 3600 + } + return +} + +// Deprecated: the RSA key pair credentials is deprecated +func (provider *RSAKeyPairCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.sessionAccessKey == nil || provider.needUpdateCredential() { + sessionAccessKey, err := provider.getCredentials() + if err != nil { + return nil, err + } + + expirationTime, err := time.Parse("2006-01-02T15:04:05Z", *sessionAccessKey.Expiration) + if err != nil { + return nil, err + } + + provider.sessionAccessKey = sessionAccessKey + provider.lastUpdateTimestamp = time.Now().Unix() + provider.expirationTimestamp = expirationTime.Unix() + } + + cc = &Credentials{ + AccessKeyId: *provider.sessionAccessKey.SessionAccessKeyId, + AccessKeySecret: *provider.sessionAccessKey.SessionAccessKeySecret, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *RSAKeyPairCredentialsProvider) needUpdateCredential() bool { + if provider.expirationTimestamp == 0 { + return true + } + + return provider.expirationTimestamp-time.Now().Unix() <= 180 +} + +func (provider *RSAKeyPairCredentialsProvider) getCredentials() (sessionAK *sessionAccessKey, err error) { + method := "POST" + host := "sts.ap-northeast-1.aliyuncs.com" + + queries := make(map[string]string) + queries["Version"] = "2015-04-01" + queries["Action"] = "GenerateSessionAccessKey" + queries["Format"] = "JSON" + queries["Timestamp"] = utils.GetTimeInFormatISO8601() + queries["SignatureMethod"] = "SHA256withRSA" + queries["SignatureVersion"] = "1.0" + queries["SignatureNonce"] = utils.GetNonce() + queries["PublicKeyId"] = provider.PublicKeyId + queries["SignatureType"] = "PRIVATEKEY" + + bodyForm := make(map[string]string) + bodyForm["DurationSeconds"] = strconv.Itoa(provider.durationSeconds) + + // caculate signature + signParams := make(map[string]string) + for key, value := range queries { + signParams[key] = value + } + for key, value := range bodyForm { + signParams[key] = value + } + + stringToSign := utils.GetUrlFormedMap(signParams) + stringToSign = strings.Replace(stringToSign, "+", "%20", -1) + stringToSign = strings.Replace(stringToSign, "*", "%2A", -1) + stringToSign = strings.Replace(stringToSign, "%7E", "~", -1) + stringToSign = url.QueryEscape(stringToSign) + stringToSign = method + "&%2F&" + stringToSign + + queries["Signature"] = utils.Sha256WithRsa(stringToSign, provider.PrivateKeyId) + + querystring := utils.GetUrlFormedMap(queries) + // do request + httpUrl := fmt.Sprintf("https://%s/?%s", host, querystring) + + body := utils.GetUrlFormedMap(bodyForm) + + httpRequest, err := hookNewRequest(http.NewRequest)(method, httpUrl, strings.NewReader(body)) + if err != nil { + return + } + + // set headers + httpRequest.Header["Accept-Encoding"] = []string{"identity"} + httpRequest.Header["Content-Type"] = []string{"application/x-www-form-urlencoded"} + httpClient := &http.Client{} + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + if httpResponse.StatusCode != http.StatusOK { + message := "refresh temp ak failed" + err = errors.NewServerError(httpResponse.StatusCode, string(responseBody), message) + return + } + + var data generateSessionAccessKeyResponse + err = json.Unmarshal(responseBody, &data) + if err != nil { + err = fmt.Errorf("refresh temp ak err, json.Unmarshal fail: %s", err.Error()) + return + } + + if data.SessionAccessKey == nil { + err = fmt.Errorf("refresh temp ak token err, fail to get credentials") + return + } + + if data.SessionAccessKey.SessionAccessKeyId == nil || data.SessionAccessKey.SessionAccessKeySecret == nil { + err = fmt.Errorf("refresh temp ak token err, fail to get credentials") + return + } + + sessionAK = data.SessionAccessKey + return +} + +func (provider *RSAKeyPairCredentialsProvider) GetProviderName() string { + return "rsa_key_pair" +} + +type RAMRoleARNCredentialsProvider struct { + // for previous credentials + accessKeyId string + accessKeySecret string + securityToken string + credentialsProvider CredentialsProvider + + roleArn string + roleSessionName string + durationSeconds int + policy string + externalId string + + // for sts endpoint + stsRegion string + enableVpc bool + stsEndpoint string + + // for http options + httpOptions *HttpOptions + + // inner + expirationTimestamp int64 + lastUpdateTimestamp int64 + previousProviderName string + sessionCredentials *SessionCredentials +} + +type RAMRoleARNCredentialsProviderBuilder struct { + provider *RAMRoleARNCredentialsProvider +} + +func NewRAMRoleARNCredentialsProviderBuilder() *RAMRoleARNCredentialsProviderBuilder { + return &RAMRoleARNCredentialsProviderBuilder{ + provider: &RAMRoleARNCredentialsProvider{}, + } +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithAccessKeyId(accessKeyId string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.accessKeyId = accessKeyId + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithAccessKeySecret(accessKeySecret string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.accessKeySecret = accessKeySecret + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithSecurityToken(securityToken string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.securityToken = securityToken + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithCredentialsProvider(credentialsProvider CredentialsProvider) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.credentialsProvider = credentialsProvider + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithRoleArn(roleArn string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.roleArn = roleArn + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithStsRegion(region string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.stsRegion = region + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithEnableVpc(enableVpc bool) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.enableVpc = enableVpc + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithStsEndpoint(endpoint string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.stsEndpoint = endpoint + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithRoleSessionName(roleSessionName string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.roleSessionName = roleSessionName + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithPolicy(policy string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.policy = policy + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithExternalId(externalId string) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.externalId = externalId + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithDurationSeconds(durationSeconds int) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.durationSeconds = durationSeconds + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *RAMRoleARNCredentialsProviderBuilder { + builder.provider.httpOptions = httpOptions + return builder +} + +func (builder *RAMRoleARNCredentialsProviderBuilder) Build() (provider *RAMRoleARNCredentialsProvider, err error) { + if builder.provider.credentialsProvider == nil { + if builder.provider.accessKeyId != "" && builder.provider.accessKeySecret != "" && builder.provider.securityToken != "" { + builder.provider.credentialsProvider, err = NewStaticSTSCredentialsProviderBuilder(). + WithAccessKeyId(builder.provider.accessKeyId). + WithAccessKeySecret(builder.provider.accessKeySecret). + WithSecurityToken(builder.provider.securityToken). + Build() + if err != nil { + return + } + } else if builder.provider.accessKeyId != "" && builder.provider.accessKeySecret != "" { + builder.provider.credentialsProvider, err = NewStaticAKCredentialsProviderBuilder(). + WithAccessKeyId(builder.provider.accessKeyId). + WithAccessKeySecret(builder.provider.accessKeySecret). + Build() + if err != nil { + return + } + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Must specify a previous credentials provider to assume role", nil) + return + } + } + + if builder.provider.roleArn == "" { + if roleArn := os.Getenv("ALIBABA_CLOUD_ROLE_ARN"); roleArn != "" { + builder.provider.roleArn = roleArn + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The RoleArn is empty", nil) + return + } + } + + if builder.provider.roleSessionName == "" { + if roleSessionName := os.Getenv("ALIBABA_CLOUD_ROLE_SESSION_NAME"); roleSessionName != "" { + builder.provider.roleSessionName = roleSessionName + } else { + builder.provider.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10) + } + } + + // duration seconds + if builder.provider.durationSeconds == 0 { + // default to 3600 + builder.provider.durationSeconds = 3600 + } + + if builder.provider.durationSeconds < 900 { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Session duration should be in the range of 900s - max session duration", nil) + return + } + + // sts endpoint + if builder.provider.stsEndpoint == "" { + if !builder.provider.enableVpc { + builder.provider.enableVpc = strings.ToLower(os.Getenv("ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED")) == "true" + } + prefix := "sts" + if builder.provider.enableVpc { + prefix = "sts-vpc" + } + if builder.provider.stsRegion != "" { + builder.provider.stsEndpoint = fmt.Sprintf("%s.%s.aliyuncs.com", prefix, builder.provider.stsRegion) + } else if region := os.Getenv("ALIBABA_CLOUD_STS_REGION"); region != "" { + builder.provider.stsEndpoint = fmt.Sprintf("%s.%s.aliyuncs.com", prefix, region) + } else { + builder.provider.stsEndpoint = "sts.aliyuncs.com" + } + } + + provider = builder.provider + return +} + +func NewRAMRoleARNCredentialsProvider(credentialsProvider CredentialsProvider, roleArn, roleSessionName string, durationSeconds int, policy, stsRegion, externalId string) (provider *RAMRoleARNCredentialsProvider, err error) { + provider = &RAMRoleARNCredentialsProvider{ + credentialsProvider: credentialsProvider, + roleArn: roleArn, + durationSeconds: durationSeconds, + policy: policy, + stsRegion: stsRegion, + externalId: externalId, + } + + if len(roleSessionName) > 0 { + provider.roleSessionName = roleSessionName + } else { + provider.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10) + } + + if durationSeconds > 0 { + if durationSeconds >= 900 && durationSeconds <= 3600 { + provider.durationSeconds = durationSeconds + } else { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Assume Role session duration should be in the range of 15min - 1hr", nil) + } + } else { + // default to 3600 + provider.durationSeconds = 3600 + } + + return +} + +func (provider *RAMRoleARNCredentialsProvider) getCredentials(cc *Credentials) (sessionCredentials *SessionCredentials, err error) { + method := "POST" + var host string + if provider.stsEndpoint != "" { + host = provider.stsEndpoint + } else if provider.stsRegion != "" { + host = fmt.Sprintf("sts.%s.aliyuncs.com", provider.stsRegion) + } else { + host = "sts.aliyuncs.com" + } + + queries := make(map[string]string) + queries["Version"] = "2015-04-01" + queries["Action"] = "AssumeRole" + queries["Format"] = "JSON" + queries["Timestamp"] = utils.GetTimeInFormatISO8601() + queries["SignatureMethod"] = "HMAC-SHA1" + queries["SignatureVersion"] = "1.0" + queries["SignatureNonce"] = utils.GetNonce() + queries["AccessKeyId"] = cc.AccessKeyId + if cc.SecurityToken != "" { + queries["SecurityToken"] = cc.SecurityToken + } + + bodyForm := make(map[string]string) + bodyForm["RoleArn"] = provider.roleArn + if provider.policy != "" { + bodyForm["Policy"] = provider.policy + } + if provider.externalId != "" { + bodyForm["ExternalId"] = provider.externalId + } + bodyForm["RoleSessionName"] = provider.roleSessionName + bodyForm["DurationSeconds"] = strconv.Itoa(provider.durationSeconds) + + // caculate signature + signParams := make(map[string]string) + for key, value := range queries { + signParams[key] = value + } + for key, value := range bodyForm { + signParams[key] = value + } + + stringToSign := utils.GetUrlFormedMap(signParams) + stringToSign = strings.Replace(stringToSign, "+", "%20", -1) + stringToSign = strings.Replace(stringToSign, "*", "%2A", -1) + stringToSign = strings.Replace(stringToSign, "%7E", "~", -1) + stringToSign = url.QueryEscape(stringToSign) + stringToSign = method + "&%2F&" + stringToSign + secret := cc.AccessKeySecret + "&" + queries["Signature"] = utils.ShaHmac1(stringToSign, secret) + + querystring := utils.GetUrlFormedMap(queries) + // do request + httpUrl := fmt.Sprintf("https://%s/?%s", host, querystring) + + body := utils.GetUrlFormedMap(bodyForm) + + httpRequest, err := hookNewRequest(http.NewRequest)(method, httpUrl, strings.NewReader(body)) + if err != nil { + return + } + + // set headers + httpRequest.Header["Accept-Encoding"] = []string{"identity"} + httpRequest.Header["Content-Type"] = []string{"application/x-www-form-urlencoded"} + + connectTimeout := 5 * time.Second + readTimeout := 10 * time.Second + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + if httpResponse.StatusCode != http.StatusOK { + message := "refresh session token failed" + err = errors.NewServerError(httpResponse.StatusCode, string(responseBody), message) + return + } + var data assumeRoleResponse + err = json.Unmarshal(responseBody, &data) + if err != nil { + err = fmt.Errorf("refresh RoleArn sts token err, json.Unmarshal fail: %s", err.Error()) + return + } + if data.Credentials == nil { + err = fmt.Errorf("refresh RoleArn sts token err, fail to get credentials") + return + } + + if data.Credentials.AccessKeyId == nil || data.Credentials.AccessKeySecret == nil || data.Credentials.SecurityToken == nil { + err = fmt.Errorf("refresh RoleArn sts token err, fail to get credentials") + return + } + + sessionCredentials = &SessionCredentials{ + AccessKeyId: *data.Credentials.AccessKeyId, + AccessKeySecret: *data.Credentials.AccessKeySecret, + SecurityToken: *data.Credentials.SecurityToken, + Expiration: *data.Credentials.Expiration, + } + return +} + +func (provider *RAMRoleARNCredentialsProvider) needUpdateCredential() (result bool) { + if provider.expirationTimestamp == 0 { + return true + } + + return provider.expirationTimestamp-time.Now().Unix() <= 180 +} + +func (provider *RAMRoleARNCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.sessionCredentials == nil || provider.needUpdateCredential() { + // 获取前置凭证 + previousCredentials, err1 := provider.credentialsProvider.GetCredentials() + if err1 != nil { + return nil, err1 + } + sessionCredentials, err2 := provider.getCredentials(previousCredentials) + if err2 != nil { + return nil, err2 + } + + expirationTime, err := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration) + if err != nil { + return nil, err + } + + provider.expirationTimestamp = expirationTime.Unix() + provider.lastUpdateTimestamp = time.Now().Unix() + provider.previousProviderName = previousCredentials.ProviderName + provider.sessionCredentials = sessionCredentials + } + if provider.previousProviderName == "" { + provider.previousProviderName = provider.credentialsProvider.GetProviderName() + } + + cc = &Credentials{ + AccessKeyId: provider.sessionCredentials.AccessKeyId, + AccessKeySecret: provider.sessionCredentials.AccessKeySecret, + SecurityToken: provider.sessionCredentials.SecurityToken, + ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), provider.previousProviderName), + } + return +} + +func (provider *RAMRoleARNCredentialsProvider) GetProviderName() string { + return "ram_role_arn" +} + +type ECSRAMRoleCredentialsProvider struct { + roleName string + disableIMDSv1 bool + + // for http options + httpOptions *HttpOptions + + sessionCredentials *SessionCredentials + expirationTimestamp int64 +} + +type ECSRAMRoleCredentialsProviderBuilder struct { + provider *ECSRAMRoleCredentialsProvider +} + +func NewECSRAMRoleCredentialsProviderBuilder() *ECSRAMRoleCredentialsProviderBuilder { + return &ECSRAMRoleCredentialsProviderBuilder{ + provider: &ECSRAMRoleCredentialsProvider{}, + } +} + +func (builder *ECSRAMRoleCredentialsProviderBuilder) WithRoleName(roleName string) *ECSRAMRoleCredentialsProviderBuilder { + builder.provider.roleName = roleName + return builder +} + +func (builder *ECSRAMRoleCredentialsProviderBuilder) WithDisableIMDSv1(disableIMDSv1 bool) *ECSRAMRoleCredentialsProviderBuilder { + builder.provider.disableIMDSv1 = disableIMDSv1 + return builder +} + +func (builder *ECSRAMRoleCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *ECSRAMRoleCredentialsProviderBuilder { + builder.provider.httpOptions = httpOptions + return builder +} + +const defaultMetadataTokenDuration = 21600 // 6 hours + +func (builder *ECSRAMRoleCredentialsProviderBuilder) Build() (provider *ECSRAMRoleCredentialsProvider, err error) { + + if strings.ToLower(os.Getenv("ALIBABA_CLOUD_ECS_METADATA_DISABLED")) == "true" { + err = fmt.Errorf("IMDS credentials is disabled") + return + } + + // 设置 roleName 默认值 + if builder.provider.roleName == "" { + builder.provider.roleName = os.Getenv("ALIBABA_CLOUD_ECS_METADATA") + } + + if !builder.provider.disableIMDSv1 { + builder.provider.disableIMDSv1 = strings.ToLower(os.Getenv("ALIBABA_CLOUD_IMDSV1_DISABLED")) == "true" + } + + provider = builder.provider + return +} + +func NewECSRAMRoleCredentialsProvider(roleName string) *ECSRAMRoleCredentialsProvider { + return &ECSRAMRoleCredentialsProvider{ + roleName: roleName, + } +} + +func (provider *ECSRAMRoleCredentialsProvider) needUpdateCredential() bool { + if provider.expirationTimestamp == 0 { + return true + } + + return provider.expirationTimestamp-time.Now().Unix() <= 180 +} + +func (provider *ECSRAMRoleCredentialsProvider) getMetadataToken() (metadataToken string, err error) { + // PUT http://100.100.100.200/latest/api/token + var requestUrl = "http://100.100.100.200/latest/api/token" + httpRequest, _err := hookNewRequest(http.NewRequest)("PUT", requestUrl, strings.NewReader("")) + if _err != nil { + if provider.disableIMDSv1 { + err = fmt.Errorf("get metadata token failed: %s", _err.Error()) + } + return + } + httpRequest.Header.Set("X-aliyun-ecs-metadata-token-ttl-seconds", strconv.Itoa(defaultMetadataTokenDuration)) + + connectTimeout := 1 * time.Second + readTimeout := 1 * time.Second + + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + httpResponse, _err := hookDo(httpClient.Do)(httpRequest) + if _err != nil { + if provider.disableIMDSv1 { + err = fmt.Errorf("get metadata token failed: %s", _err.Error()) + } + return + } + + defer httpResponse.Body.Close() + + responseBody, _err := ioutil.ReadAll(httpResponse.Body) + if _err != nil { + if provider.disableIMDSv1 { + err = fmt.Errorf("get metadata token failed: %s", _err.Error()) + } + return + } + + if httpResponse.StatusCode != http.StatusOK { + if provider.disableIMDSv1 { + err = errors.NewServerError(httpResponse.StatusCode, string(responseBody), "refresh Ecs sts token err") + } + return + } + + metadataToken = strings.TrimSpace(string(responseBody)) + return +} + +func (provider *ECSRAMRoleCredentialsProvider) getRoleName() (roleName string, err error) { + connectTimeout := 1 * time.Second + readTimeout := 1 * time.Second + + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + var securityCredURL = "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + httpRequest, err := hookNewRequest(http.NewRequest)("GET", securityCredURL, strings.NewReader("")) + if err != nil { + err = fmt.Errorf("get role name failed: %s", err.Error()) + return + } + + metadataToken, err := provider.getMetadataToken() + if err != nil { + return + } + if metadataToken != "" { + httpRequest.Header.Set("X-aliyun-ecs-metadata-token", metadataToken) + } + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + err = fmt.Errorf("get role name failed: %s", err.Error()) + return + } + + if httpResponse.StatusCode != http.StatusOK { + err = fmt.Errorf("get role name failed: request %s %d", securityCredURL, httpResponse.StatusCode) + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + roleName = strings.TrimSpace(string(responseBody)) + return +} + +func (provider *ECSRAMRoleCredentialsProvider) getCredentials() (sessionCredentials *SessionCredentials, err error) { + roleName := provider.roleName + if roleName == "" { + roleName, err = provider.getRoleName() + if err != nil { + return + } + } + + connectTimeout := 1 * time.Second + readTimeout := 1 * time.Second + + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + var requestUrl = "http://100.100.100.200/latest/meta-data/ram/security-credentials/" + roleName + httpRequest, err := hookNewRequest(http.NewRequest)("GET", requestUrl, strings.NewReader("")) + if err != nil { + err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) + return + } + + metadataToken, err := provider.getMetadataToken() + if err != nil { + return + } + if metadataToken != "" { + httpRequest.Header.Set("X-aliyun-ecs-metadata-token", metadataToken) + } + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + if httpResponse.StatusCode != http.StatusOK { + err = fmt.Errorf("refresh Ecs sts token err, httpStatus: %d, message = %s", httpResponse.StatusCode, string(responseBody)) + return + } + + var data ecsRAMRoleCredentials + err = json.Unmarshal(responseBody, &data) + if err != nil { + err = fmt.Errorf("refresh Ecs sts token err, json.Unmarshal fail: %s", err.Error()) + return + } + + if data.AccessKeyId == nil || data.AccessKeySecret == nil || data.SecurityToken == nil { + err = fmt.Errorf("refresh Ecs sts token err, fail to get credentials") + return + } + + if *data.Code != "Success" { + err = fmt.Errorf("refresh Ecs sts token err, Code is not Success") + return + } + + sessionCredentials = &SessionCredentials{ + AccessKeyId: *data.AccessKeyId, + AccessKeySecret: *data.AccessKeySecret, + SecurityToken: *data.SecurityToken, + Expiration: *data.Expiration, + } + return +} + +func (provider *ECSRAMRoleCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.sessionCredentials == nil || provider.needUpdateCredential() { + sessionCredentials, err1 := provider.getCredentials() + if err1 != nil { + return nil, err1 + } + + provider.sessionCredentials = sessionCredentials + expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration) + if err2 != nil { + return nil, err2 + } + provider.expirationTimestamp = expirationTime.Unix() + } + + cc = &Credentials{ + AccessKeyId: provider.sessionCredentials.AccessKeyId, + AccessKeySecret: provider.sessionCredentials.AccessKeySecret, + SecurityToken: provider.sessionCredentials.SecurityToken, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *ECSRAMRoleCredentialsProvider) GetProviderName() string { + return "ecs_ram_role" +} + +type OIDCCredentialsProvider struct { + oidcProviderARN string + oidcTokenFilePath string + roleArn string + roleSessionName string + durationSeconds int + policy string + // for sts endpoint + stsRegion string + enableVpc bool + stsEndpoint string + lastUpdateTimestamp int64 + expirationTimestamp int64 + sessionCredentials *SessionCredentials + // for http options + httpOptions *HttpOptions +} + +type OIDCCredentialsProviderBuilder struct { + provider *OIDCCredentialsProvider +} + +func NewOIDCCredentialsProviderBuilder() *OIDCCredentialsProviderBuilder { + return &OIDCCredentialsProviderBuilder{ + provider: &OIDCCredentialsProvider{}, + } +} + +func (b *OIDCCredentialsProviderBuilder) WithOIDCProviderARN(oidcProviderArn string) *OIDCCredentialsProviderBuilder { + b.provider.oidcProviderARN = oidcProviderArn + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithOIDCTokenFilePath(oidcTokenFilePath string) *OIDCCredentialsProviderBuilder { + b.provider.oidcTokenFilePath = oidcTokenFilePath + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithRoleArn(roleArn string) *OIDCCredentialsProviderBuilder { + b.provider.roleArn = roleArn + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithRoleSessionName(roleSessionName string) *OIDCCredentialsProviderBuilder { + b.provider.roleSessionName = roleSessionName + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithDurationSeconds(durationSeconds int) *OIDCCredentialsProviderBuilder { + b.provider.durationSeconds = durationSeconds + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithStsRegion(region string) *OIDCCredentialsProviderBuilder { + b.provider.stsRegion = region + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithEnableVpc(enableVpc bool) *OIDCCredentialsProviderBuilder { + b.provider.enableVpc = enableVpc + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithSTSEndpoint(stsEndpoint string) *OIDCCredentialsProviderBuilder { + b.provider.stsEndpoint = stsEndpoint + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithPolicy(policy string) *OIDCCredentialsProviderBuilder { + b.provider.policy = policy + return b +} + +func (b *OIDCCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *OIDCCredentialsProviderBuilder { + b.provider.httpOptions = httpOptions + return b +} + +func (b *OIDCCredentialsProviderBuilder) Build() (provider *OIDCCredentialsProvider, err error) { + provider = b.provider + + if provider.roleSessionName == "" { + provider.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10) + } + + if provider.oidcTokenFilePath == "" { + provider.oidcTokenFilePath = os.Getenv("ALIBABA_CLOUD_OIDC_TOKEN_FILE") + } + + if provider.oidcTokenFilePath == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "OIDCTokenFilePath can not be empty", nil) + return + } + + if provider.oidcProviderARN == "" { + provider.oidcProviderARN = os.Getenv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN") + } + + if provider.oidcProviderARN == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "OIDCProviderARN can not be empty", nil) + return + } + + if provider.roleArn == "" { + provider.roleArn = os.Getenv("ALIBABA_CLOUD_ROLE_ARN") + } + + if provider.roleArn == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "RoleArn can not be empty", nil) + return + } + + if provider.durationSeconds == 0 { + provider.durationSeconds = 3600 + } + + if provider.durationSeconds < 900 || provider.durationSeconds > 3600 { + err = errors.NewClientError(errors.InvalidParamErrorCode, "Assume Role session duration should be in the range of 15min - 1hr", nil) + } + + // sts endpoint + if provider.stsEndpoint == "" { + if !provider.enableVpc { + provider.enableVpc = strings.ToLower(os.Getenv("ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED")) == "true" + } + prefix := "sts" + if provider.enableVpc { + prefix = "sts-vpc" + } + if provider.stsRegion != "" { + provider.stsEndpoint = fmt.Sprintf("%s.%s.aliyuncs.com", prefix, provider.stsRegion) + } else if region := os.Getenv("ALIBABA_CLOUD_STS_REGION"); region != "" { + provider.stsEndpoint = fmt.Sprintf("%s.%s.aliyuncs.com", prefix, region) + } else { + provider.stsEndpoint = "sts.aliyuncs.com" + } + } + + return +} + +func (provider *OIDCCredentialsProvider) getCredentials() (sessionCredentials *SessionCredentials, err error) { + method := "POST" + var host string + if provider.stsEndpoint != "" { + host = provider.stsEndpoint + } else if provider.stsRegion != "" { + host = fmt.Sprintf("sts.%s.aliyuncs.com", provider.stsRegion) + } else { + host = "sts.aliyuncs.com" + } + + queries := make(map[string]string) + queries["Version"] = "2015-04-01" + queries["Action"] = "AssumeRoleWithOIDC" + queries["Format"] = "JSON" + queries["Timestamp"] = utils.GetTimeInFormatISO8601() + + bodyForm := make(map[string]string) + bodyForm["RoleArn"] = provider.roleArn + bodyForm["OIDCProviderArn"] = provider.oidcProviderARN + token, err := ioutil.ReadFile(provider.oidcTokenFilePath) + if err != nil { + return + } + + bodyForm["OIDCToken"] = string(token) + if provider.policy != "" { + bodyForm["Policy"] = provider.policy + } + + bodyForm["RoleSessionName"] = provider.roleSessionName + bodyForm["DurationSeconds"] = strconv.Itoa(provider.durationSeconds) + + // caculate signature + signParams := make(map[string]string) + for key, value := range queries { + signParams[key] = value + } + for key, value := range bodyForm { + signParams[key] = value + } + + querystring := utils.GetUrlFormedMap(queries) + // do request + httpUrl := fmt.Sprintf("https://%s/?%s", host, querystring) + + body := utils.GetUrlFormedMap(bodyForm) + + httpRequest, err := hookNewRequest(http.NewRequest)(method, httpUrl, strings.NewReader(body)) + if err != nil { + return + } + + // set headers + httpRequest.Header["Accept-Encoding"] = []string{"identity"} + httpRequest.Header["Content-Type"] = []string{"application/x-www-form-urlencoded"} + + connectTimeout := 5 * time.Second + readTimeout := 10 * time.Second + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + if httpResponse.StatusCode != http.StatusOK { + message := "get session token failed" + err = errors.NewServerError(httpResponse.StatusCode, string(responseBody), message) + return + } + var data assumeRoleResponse + err = json.Unmarshal(responseBody, &data) + if err != nil { + err = fmt.Errorf("get oidc sts token err, json.Unmarshal fail: %s", err.Error()) + return + } + if data.Credentials == nil { + err = fmt.Errorf("get oidc sts token err, fail to get credentials") + return + } + + if data.Credentials.AccessKeyId == nil || data.Credentials.AccessKeySecret == nil || data.Credentials.SecurityToken == nil { + err = fmt.Errorf("refresh RoleArn sts token err, fail to get credentials") + return + } + + sessionCredentials = &SessionCredentials{ + AccessKeyId: *data.Credentials.AccessKeyId, + AccessKeySecret: *data.Credentials.AccessKeySecret, + SecurityToken: *data.Credentials.SecurityToken, + Expiration: *data.Credentials.Expiration, + } + return +} + +func (provider *OIDCCredentialsProvider) needUpdateCredential() (result bool) { + if provider.expirationTimestamp == 0 { + return true + } + + return provider.expirationTimestamp-time.Now().Unix() <= 180 +} + +func (provider *OIDCCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.sessionCredentials == nil || provider.needUpdateCredential() { + sessionCredentials, err1 := provider.getCredentials() + if err1 != nil { + return nil, err1 + } + + provider.sessionCredentials = sessionCredentials + expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration) + if err2 != nil { + return nil, err2 + } + + provider.lastUpdateTimestamp = time.Now().Unix() + provider.expirationTimestamp = expirationTime.Unix() + } + + cc = &Credentials{ + AccessKeyId: provider.sessionCredentials.AccessKeyId, + AccessKeySecret: provider.sessionCredentials.AccessKeySecret, + SecurityToken: provider.sessionCredentials.SecurityToken, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *OIDCCredentialsProvider) GetProviderName() string { + return "oidc_role_arn" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/default_credentials_provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/default_credentials_provider.go new file mode 100644 index 00000000..c956b4cd --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/default_credentials_provider.go @@ -0,0 +1,106 @@ +package credentials + +import ( + "fmt" + "os" + "strings" +) + +type DefaultCredentialsProvider struct { + providerChain []CredentialsProvider + lastUsedProvider CredentialsProvider +} + +func NewDefaultCredentialsProvider() (provider *DefaultCredentialsProvider) { + providers := []CredentialsProvider{} + + // Add static ak or sts credentials provider + providers = append(providers, NewEnvironmentVariableCredentialsProvider()) + + // oidc check + oidcProvider, err := NewOIDCCredentialsProviderBuilder().Build() + if err == nil { + providers = append(providers, oidcProvider) + } + + // cli credentials provider + providers = append(providers, NewCLIProfileCredentialsProviderBuilder().Build()) + + // profile credentials provider + // providers = append(providers) + providers = append(providers, NewProfileCredentialsProviderBuilder().Build()) + + // Add IMDS + ecsRamRoleProvider, err := NewECSRAMRoleCredentialsProviderBuilder().Build() + if err == nil { + providers = append(providers, ecsRamRoleProvider) + } + + // credentials uri + if os.Getenv("ALIBABA_CLOUD_CREDENTIALS_URI") != "" { + credentialsUriProvider, err := NewURLCredentialsProviderBuilderBuilder().Build() + if err == nil { + providers = append(providers, credentialsUriProvider) + } + } + + return &DefaultCredentialsProvider{ + providerChain: providers, + } +} + +func (provider *DefaultCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.lastUsedProvider != nil { + inner, err1 := provider.lastUsedProvider.GetCredentials() + if err1 != nil { + err = err1 + return + } + + providerName := inner.ProviderName + if providerName == "" { + providerName = provider.lastUsedProvider.GetProviderName() + } + + cc = &Credentials{ + AccessKeyId: inner.AccessKeyId, + AccessKeySecret: inner.AccessKeySecret, + SecurityToken: inner.SecurityToken, + ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), providerName), + } + return + } + + errors := []string{} + for _, p := range provider.providerChain { + provider.lastUsedProvider = p + inner, errInLoop := p.GetCredentials() + + if errInLoop != nil { + errors = append(errors, errInLoop.Error()) + // 如果有错误,进入下一个获取过程 + continue + } + + if inner != nil { + providerName := inner.ProviderName + if providerName == "" { + providerName = p.GetProviderName() + } + cc = &Credentials{ + AccessKeyId: inner.AccessKeyId, + AccessKeySecret: inner.AccessKeySecret, + SecurityToken: inner.SecurityToken, + ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), providerName), + } + return + } + } + + err = fmt.Errorf("unable to get credentials from any of the providers in the chain: %s", strings.Join(errors, ", ")) + return +} + +func (provider *DefaultCredentialsProvider) GetProviderName() string { + return "default" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/env_credentials_provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/env_credentials_provider.go new file mode 100644 index 00000000..bda1ae82 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/env_credentials_provider.go @@ -0,0 +1,44 @@ +package credentials + +import ( + "fmt" + "os" +) + +type EnvironmentVariableCredentialsProvider struct { +} + +func NewEnvironmentVariableCredentialsProvider() (provider *EnvironmentVariableCredentialsProvider) { + return &EnvironmentVariableCredentialsProvider{} +} + +func (provider *EnvironmentVariableCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + accessKeyId := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID") + + if accessKeyId == "" { + err = fmt.Errorf("unable to get credentials from enviroment variables, Access key ID must be specified via environment variable (ALIBABA_CLOUD_ACCESS_KEY_ID)") + return + } + + accessKeySecret := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET") + + if accessKeySecret == "" { + err = fmt.Errorf("unable to get credentials from enviroment variables, Access key secret must be specified via environment variable (ALIBABA_CLOUD_ACCESS_KEY_SECRET)") + return + } + + securityToken := os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN") + + cc = &Credentials{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + SecurityToken: securityToken, + ProviderName: provider.GetProviderName(), + } + + return +} + +func (provider *EnvironmentVariableCredentialsProvider) GetProviderName() string { + return "env" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/profile_credentials_provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/profile_credentials_provider.go new file mode 100644 index 00000000..52b9d12b --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/profile_credentials_provider.go @@ -0,0 +1,179 @@ +package credentials + +import ( + "errors" + "fmt" + "os" + "path" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal" + "gopkg.in/ini.v1" +) + +type ProfileCredentialsProvider struct { + profileName string + innerProvider CredentialsProvider +} + +type ProfileCredentialsProviderBuilder struct { + provider *ProfileCredentialsProvider +} + +func NewProfileCredentialsProviderBuilder() (builder *ProfileCredentialsProviderBuilder) { + return &ProfileCredentialsProviderBuilder{ + provider: &ProfileCredentialsProvider{}, + } +} + +func (b *ProfileCredentialsProviderBuilder) WithProfileName(profileName string) *ProfileCredentialsProviderBuilder { + b.provider.profileName = profileName + return b +} + +func (b *ProfileCredentialsProviderBuilder) Build() (provider *ProfileCredentialsProvider) { + // 优先级: + // 1. 使用显示指定的 profileName + // 2. 使用环境变量(ALIBABA_CLOUD_PROFILE)指定的 profileName + // 3. 兜底使用 default 作为 profileName + b.provider.profileName = internal.GetDefaultString(b.provider.profileName, os.Getenv("ALIBABA_CLOUD_PROFILE"), "default") + + provider = b.provider + return +} + +func (provider *ProfileCredentialsProvider) getCredentialsProvider(ini *ini.File) (credentialsProvider CredentialsProvider, err error) { + section, err := ini.GetSection(provider.profileName) + if err != nil { + err = errors.New("ERROR: Can not load section" + err.Error()) + return + } + + value, err := section.GetKey("type") + if err != nil { + err = errors.New("ERROR: Can not find credential type" + err.Error()) + return + } + + switch value.String() { + case "access_key": + value1, err1 := section.GetKey("access_key_id") + value2, err2 := section.GetKey("access_key_secret") + if err1 != nil || err2 != nil { + err = errors.New("ERROR: Failed to get value") + return + } + + if value1.String() == "" || value2.String() == "" { + err = errors.New("ERROR: Value can't be empty") + return + } + + credentialsProvider, err = NewStaticAKCredentialsProviderBuilder(). + WithAccessKeyId(value1.String()). + WithAccessKeySecret(value2.String()). + Build() + case "ecs_ram_role": + value1, err1 := section.GetKey("role_name") + if err1 != nil { + err = errors.New("ERROR: Failed to get value") + return + } + credentialsProvider, err = NewECSRAMRoleCredentialsProviderBuilder().WithRoleName(value1.String()).Build() + case "ram_role_arn": + value1, err1 := section.GetKey("access_key_id") + value2, err2 := section.GetKey("access_key_secret") + value3, err3 := section.GetKey("role_arn") + value4, err4 := section.GetKey("role_session_name") + if err1 != nil || err2 != nil || err3 != nil || err4 != nil { + err = errors.New("ERROR: Failed to get value") + return + } + if value1.String() == "" || value2.String() == "" || value3.String() == "" || value4.String() == "" { + err = errors.New("ERROR: Value can't be empty") + return + } + previous, err5 := NewStaticAKCredentialsProviderBuilder(). + WithAccessKeyId(value1.String()). + WithAccessKeySecret(value2.String()). + Build() + if err5 != nil { + err = errors.New("get previous credentials provider failed") + return + } + rawPolicy, _ := section.GetKey("policy") + policy := "" + if rawPolicy != nil { + policy = rawPolicy.String() + } + + credentialsProvider, err = NewRAMRoleARNCredentialsProviderBuilder(). + WithCredentialsProvider(previous). + WithRoleArn(value3.String()). + WithRoleSessionName(value4.String()). + WithPolicy(policy). + WithDurationSeconds(3600). + Build() + default: + err = errors.New("ERROR: Failed to get credential") + } + return +} + +func (provider *ProfileCredentialsProvider) getIni() (iniInfo *ini.File, err error) { + sharedCfgPath := os.Getenv("ALIBABA_CLOUD_CREDENTIALS_FILE") + if sharedCfgPath == "" { + homeDir := getHomePath() + if homeDir == "" { + err = fmt.Errorf("cannot found home dir") + return + } + + sharedCfgPath = path.Join(homeDir, ".alibabacloud/credentials") + } + + iniInfo, err = ini.Load(sharedCfgPath) + if err != nil { + err = errors.New("ERROR: Can not open file" + err.Error()) + return + } + + return +} + +func (provider *ProfileCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.innerProvider == nil { + var iniInfo *ini.File + iniInfo, err = provider.getIni() + if err != nil { + return + } + + provider.innerProvider, err = provider.getCredentialsProvider(iniInfo) + if err != nil { + return + } + } + + innerCC, err := provider.innerProvider.GetCredentials() + if err != nil { + return + } + + providerName := innerCC.ProviderName + if providerName == "" { + providerName = provider.innerProvider.GetProviderName() + } + + cc = &Credentials{ + AccessKeyId: innerCC.AccessKeyId, + AccessKeySecret: innerCC.AccessKeySecret, + SecurityToken: innerCC.SecurityToken, + ProviderName: fmt.Sprintf("%s/%s", provider.GetProviderName(), providerName), + } + + return +} + +func (provider ProfileCredentialsProvider) GetProviderName() string { + return "profile" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go index 00d688eb..63f462ae 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/rsa_key_pair_credential.go @@ -1,11 +1,13 @@ package credentials +// Deprecated: the RSA key pair is deprecated type RsaKeyPairCredential struct { PrivateKey string PublicKeyId string SessionExpiration int } +// Deprecated: the RSA key pair is deprecated func NewRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int) *RsaKeyPairCredential { return &RsaKeyPairCredential{ PrivateKey: privateKey, diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/uri_credentials_provider.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/uri_credentials_provider.go new file mode 100644 index 00000000..5bc41f54 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials/uri_credentials_provider.go @@ -0,0 +1,169 @@ +package credentials + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "os" + "strings" + "time" + + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" +) + +type URLCredentialsProvider struct { + url string + // for sts + sessionCredentials *SessionCredentials + // for http options + httpOptions *HttpOptions + // inner + expirationTimestamp int64 +} + +type URLCredentialsProviderBuilder struct { + provider *URLCredentialsProvider +} + +func NewURLCredentialsProviderBuilderBuilder() *URLCredentialsProviderBuilder { + return &URLCredentialsProviderBuilder{ + provider: &URLCredentialsProvider{}, + } +} + +func (builder *URLCredentialsProviderBuilder) WithUrl(url string) *URLCredentialsProviderBuilder { + builder.provider.url = url + return builder +} + +func (builder *URLCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *URLCredentialsProviderBuilder { + builder.provider.httpOptions = httpOptions + return builder +} + +func (builder *URLCredentialsProviderBuilder) Build() (provider *URLCredentialsProvider, err error) { + + if builder.provider.url == "" { + builder.provider.url = os.Getenv("ALIBABA_CLOUD_CREDENTIALS_URI") + } + + if builder.provider.url == "" { + err = errors.NewClientError(errors.InvalidParamErrorCode, "The url is empty", nil) + return + } + + provider = builder.provider + return +} + +type urlResponse struct { + AccessKeyId *string `json:"AccessKeyId"` + AccessKeySecret *string `json:"AccessKeySecret"` + SecurityToken *string `json:"SecurityToken"` + Expiration *string `json:"Expiration"` +} + +func (provider *URLCredentialsProvider) getCredentials() (session *SessionCredentials, err error) { + connectTimeout := 5 * time.Second + readTimeout := 10 * time.Second + if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { + connectTimeout = provider.httpOptions.ConnectTimeout + } + if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { + readTimeout = provider.httpOptions.ReadTimeout + } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.DialContext = func(ctx context.Context, network, address string) (net.Conn, error) { + return (&net.Dialer{ + Timeout: connectTimeout, + DualStack: true, + }).DialContext(ctx, network, address) + } + + httpClient := &http.Client{ + Timeout: connectTimeout + readTimeout, + Transport: transport, + } + + httpRequest, err := hookNewRequest(http.NewRequest)("GET", provider.url, strings.NewReader("")) + if err != nil { + return + } + + httpResponse, err := hookDo(httpClient.Do)(httpRequest) + if err != nil { + fmt.Println(err) + return + } + + defer httpResponse.Body.Close() + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + if err != nil { + return + } + + if httpResponse.StatusCode != http.StatusOK { + err = fmt.Errorf("get credentials from %s failed: %s", provider.url, string(responseBody)) + return + } + + var resp urlResponse + err = json.Unmarshal(responseBody, &resp) + if err != nil { + err = fmt.Errorf("get credentials from %s failed with error, json unmarshal fail: %s", provider.url, err.Error()) + return + } + + if resp.AccessKeyId == nil || resp.AccessKeySecret == nil || resp.SecurityToken == nil || resp.Expiration == nil { + err = fmt.Errorf("refresh credentials from %s failed: %s", provider.url, string(responseBody)) + return + } + + session = &SessionCredentials{ + AccessKeyId: *resp.AccessKeyId, + AccessKeySecret: *resp.AccessKeySecret, + SecurityToken: *resp.SecurityToken, + Expiration: *resp.Expiration, + } + return +} + +func (provider *URLCredentialsProvider) needUpdateCredential() (result bool) { + if provider.expirationTimestamp == 0 { + return true + } + + return provider.expirationTimestamp-time.Now().Unix() <= 180 +} + +func (provider *URLCredentialsProvider) GetCredentials() (cc *Credentials, err error) { + if provider.sessionCredentials == nil || provider.needUpdateCredential() { + sessionCredentials, err1 := provider.getCredentials() + if err1 != nil { + return nil, err1 + } + + provider.sessionCredentials = sessionCredentials + expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration) + if err2 != nil { + return nil, err2 + } + provider.expirationTimestamp = expirationTime.Unix() + } + + cc = &Credentials{ + AccessKeyId: provider.sessionCredentials.AccessKeyId, + AccessKeySecret: provider.sessionCredentials.AccessKeySecret, + SecurityToken: provider.sessionCredentials.SecurityToken, + ProviderName: provider.GetProviderName(), + } + return +} + +func (provider *URLCredentialsProvider) GetProviderName() string { + return "credential_uri" +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go index 887f5020..941b68df 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/algorithms.go @@ -24,6 +24,7 @@ import ( "encoding/base64" ) +// Deprecated: use utils.ShaHmac1() instead of func ShaHmac1(source, secret string) string { key := []byte(secret) hmac := hmac.New(sha1.New, key) @@ -33,6 +34,7 @@ func ShaHmac1(source, secret string) string { return signedString } +// Deprecated: use utils.Sha256WithRsa() instead of func Sha256WithRsa(source, secret string) string { // block, _ := pem.Decode([]byte(secret)) decodeString, err := base64.StdEncoding.DecodeString(secret) diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go index bc4f35b8..abd888c9 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_access_key.go @@ -16,6 +16,7 @@ package signers import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" ) type AccessKeySigner struct { @@ -50,5 +51,5 @@ func (signer *AccessKeySigner) GetAccessKeyId() (accessKeyId string, err error) func (signer *AccessKeySigner) Sign(stringToSign, secretSuffix string) string { secret := signer.credential.AccessKeySecret + secretSuffix - return ShaHmac1(stringToSign, secret) + return utils.ShaHmac1(stringToSign, secret) } diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go index 73788429..d570e9c2 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ecs_ram_role.go @@ -24,6 +24,7 @@ import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" jmespath "github.com/jmespath/go-jmespath" ) @@ -89,7 +90,7 @@ func (signer *EcsRamRoleSigner) GetExtraParam() map[string]string { func (signer *EcsRamRoleSigner) Sign(stringToSign, secretSuffix string) string { secret := signer.sessionCredential.AccessKeySecret + secretSuffix - return ShaHmac1(stringToSign, secret) + return utils.ShaHmac1(stringToSign, secret) } func (signer *EcsRamRoleSigner) buildCommonRequest() (request *requests.CommonRequest, err error) { @@ -103,7 +104,9 @@ func (signer *EcsRamRoleSigner) refreshApi(request *requests.CommonRequest) (res err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) return } - httpClient := &http.Client{} + httpClient := &http.Client{ + Timeout: 5 * time.Second, + } httpResponse, err := httpClient.Do(httpRequest) if err != nil { err = fmt.Errorf("refresh Ecs sts token err: %s", err.Error()) diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go index 19273d5a..4f1308c9 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_key_pair.go @@ -24,9 +24,11 @@ import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" jmespath "github.com/jmespath/go-jmespath" ) +// Deprecated: RSA key pair is deprecated type SignerKeyPair struct { *credentialUpdater sessionCredential *SessionCredential @@ -34,6 +36,7 @@ type SignerKeyPair struct { commonApi func(request *requests.CommonRequest, signer interface{}) (response *responses.CommonResponse, err error) } +// Deprecated: RSA key pair is deprecated func NewSignerKeyPair(credential *credentials.RsaKeyPairCredential, commonApi func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error)) (signer *SignerKeyPair, err error) { signer = &SignerKeyPair{ credential: credential, @@ -98,7 +101,7 @@ func (signer *SignerKeyPair) GetExtraParam() map[string]string { func (signer *SignerKeyPair) Sign(stringToSign, secretSuffix string) string { secret := signer.sessionCredential.AccessKeySecret + secretSuffix - return ShaHmac1(stringToSign, secret) + return utils.ShaHmac1(stringToSign, secret) } func (signer *SignerKeyPair) buildCommonRequest() (request *requests.CommonRequest, err error) { diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go index abfcfb85..df3fcfd5 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_ram_role_arn.go @@ -25,6 +25,7 @@ import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" jmespath "github.com/jmespath/go-jmespath" ) @@ -109,7 +110,7 @@ func (signer *RamRoleArnSigner) GetExtraParam() map[string]string { func (signer *RamRoleArnSigner) Sign(stringToSign, secretSuffix string) string { secret := signer.sessionCredential.AccessKeySecret + secretSuffix - return ShaHmac1(stringToSign, secret) + return utils.ShaHmac1(stringToSign, secret) } func (signer *RamRoleArnSigner) buildCommonRequest() (request *requests.CommonRequest, err error) { diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go index d0ce36c3..822ec6ab 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_sts_token.go @@ -16,6 +16,7 @@ package signers import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" ) type StsTokenSigner struct { @@ -50,5 +51,5 @@ func (signer *StsTokenSigner) GetExtraParam() map[string]string { func (signer *StsTokenSigner) Sign(stringToSign, secretSuffix string) string { secret := signer.credential.AccessKeySecret + secretSuffix - return ShaHmac1(stringToSign, secret) + return utils.ShaHmac1(stringToSign, secret) } diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go index 97348529..112b1ae0 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers/signer_v2.go @@ -16,6 +16,7 @@ package signers import ( "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils" ) type SignerV2 struct { @@ -50,5 +51,5 @@ func (signer *SignerV2) GetAccessKeyId() (accessKeyId string, err error) { func (signer *SignerV2) Sign(stringToSign, secretSuffix string) string { secret := signer.credential.PrivateKey - return Sha256WithRsa(stringToSign, secret) + return utils.Sha256WithRsa(stringToSign, secret) } diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/path.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/path.go new file mode 100644 index 00000000..974fa35c --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/path.go @@ -0,0 +1,16 @@ +package internal + +import ( + "os" + "runtime" +) + +// GetHomePath return home directory according to the system. +// if the environmental virables does not exist, will return empty string +func GetHomePath() string { + if runtime.GOOS == "windows" { + return os.Getenv("USERPROFILE") + } + + return os.Getenv("HOME") +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/utils.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/utils.go new file mode 100644 index 00000000..394a8871 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal/utils.go @@ -0,0 +1,31 @@ +package internal + +import "os" + +// Get first non-empty value +func GetDefaultString(values ...string) string { + for _, v := range values { + if v != "" { + return v + } + } + + return "" +} + +// set back the memoried enviroment variables +type Rollback func() + +func Memory(keys ...string) Rollback { + // remenber enviroment variables + m := make(map[string]string) + for _, key := range keys { + m[key] = os.Getenv(key) + } + + return func() { + for _, key := range keys { + os.Setenv(key, m[key]) + } + } +} diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go index 3d591565..0893c06a 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests/acs_request.go @@ -200,7 +200,7 @@ func (request *baseRequest) AppendUserAgent(key, value string) { request.userAgent = make(map[string]string) } if strings.ToLower(key) != "core" && strings.ToLower(key) != "go" { - for tag, _ := range request.userAgent { + for tag := range request.userAgent { if tag == key { request.userAgent[tag] = value newkey = false @@ -403,7 +403,7 @@ func handleRepeatedParams(request AcsRequest, dataValue reflect.Value, prefix, n return nil } -func handleParam(request AcsRequest, dataValue reflect.Value, prefix, key, fieldPosition string) (err error) { +func handleParam(request AcsRequest, dataValue reflect.Value, key, fieldPosition string) (err error) { if dataValue.Type().String() == "[]string" { if dataValue.IsNil() { return @@ -447,12 +447,12 @@ func handleMap(request AcsRequest, dataValue reflect.Value, prefix, name, fieldP key := prefix + name + ".#" + strconv.Itoa(k.Len()) + "#" + k.String() if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { elementValue := v.Elem() - err = handleParam(request, elementValue, prefix, key, fieldPosition) + err = handleParam(request, elementValue, key, fieldPosition) if err != nil { return err } } else if v.IsValid() && v.IsNil() { - err = handleParam(request, v, prefix, key, fieldPosition) + err = handleParam(request, v, key, fieldPosition) if err != nil { return err } diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/doc.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/doc.go new file mode 100644 index 00000000..67e1c5a6 --- /dev/null +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/doc.go @@ -0,0 +1,4 @@ +// The utils package just degisned for github.com/aliyun/alibaba-clouc-sdk-go/sdk inner. +// Don't use it in other places, we don't keep compability +// We will change it to internal package in the future +package utils diff --git a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go index 79727d87..37778394 100644 --- a/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go +++ b/vendor/github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils/utils.go @@ -16,11 +16,17 @@ package utils import ( "bytes" + "crypto" + "crypto/hmac" "crypto/md5" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" "encoding/base64" "encoding/hex" "fmt" - "math/rand" + mathrand "math/rand" "net/url" "reflect" "runtime" @@ -46,7 +52,7 @@ func GetNonce() (uuidHex string) { routineId := getGID() currentTime := time.Now().UnixNano() / 1e6 seq := atomic.AddInt64(&seqId, 1) - randNum := rand.Int63() + randNum := mathrand.Int63() msg := fmt.Sprintf("%d-%d-%d-%d-%d", processStartTime, routineId, currentTime, seq, randNum) h := md5.New() h.Write([]byte(msg)) @@ -82,6 +88,7 @@ func GetUrlFormedMap(source map[string]string) (urlEncoded string) { return } +// Deprecated: don't use it func InitStructWithDefaultTag(bean interface{}) { configType := reflect.TypeOf(bean) for i := 0; i < configType.Elem().NumField(); i++ { @@ -106,3 +113,35 @@ func InitStructWithDefaultTag(bean interface{}) { } } } + +func ShaHmac1(source, secret string) string { + key := []byte(secret) + hmac := hmac.New(sha1.New, key) + hmac.Write([]byte(source)) + signedBytes := hmac.Sum(nil) + signedString := base64.StdEncoding.EncodeToString(signedBytes) + return signedString +} + +func Sha256WithRsa(source, secret string) string { + // block, _ := pem.Decode([]byte(secret)) + decodeString, err := base64.StdEncoding.DecodeString(secret) + if err != nil { + panic(err) + } + private, err := x509.ParsePKCS8PrivateKey(decodeString) + if err != nil { + panic(err) + } + + h := crypto.Hash.New(crypto.SHA256) + h.Write([]byte(source)) + hashed := h.Sum(nil) + signature, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), + crypto.SHA256, hashed) + if err != nil { + panic(err) + } + + return base64.StdEncoding.EncodeToString(signature) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0ee07a71..89ff71dd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -46,11 +46,12 @@ github.com/alibabacloud-go/tea-utils/v2/service # github.com/alibabacloud-go/tea-xml v1.1.3 ## explicit; go 1.14 github.com/alibabacloud-go/tea-xml/service -# github.com/aliyun/alibaba-cloud-sdk-go v1.62.708 +# github.com/aliyun/alibaba-cloud-sdk-go v1.63.56 ## explicit; go 1.13 github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors +github.com/aliyun/alibaba-cloud-sdk-go/sdk/internal github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses github.com/aliyun/alibaba-cloud-sdk-go/sdk/utils