github.com/aliyun/credentials-go@v1.4.7/credentials/providers/uri.go (about) 1 package providers 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "net/http" 8 "os" 9 "time" 10 11 httputil "github.com/aliyun/credentials-go/credentials/internal/http" 12 ) 13 14 type URLCredentialsProvider struct { 15 url string 16 // for sts 17 sessionCredentials *sessionCredentials 18 // for http options 19 httpOptions *HttpOptions 20 // inner 21 expirationTimestamp int64 22 } 23 24 type URLCredentialsProviderBuilder struct { 25 provider *URLCredentialsProvider 26 } 27 28 func NewURLCredentialsProviderBuilder() *URLCredentialsProviderBuilder { 29 return &URLCredentialsProviderBuilder{ 30 provider: &URLCredentialsProvider{}, 31 } 32 } 33 34 func (builder *URLCredentialsProviderBuilder) WithUrl(url string) *URLCredentialsProviderBuilder { 35 builder.provider.url = url 36 return builder 37 } 38 39 func (builder *URLCredentialsProviderBuilder) WithHttpOptions(httpOptions *HttpOptions) *URLCredentialsProviderBuilder { 40 builder.provider.httpOptions = httpOptions 41 return builder 42 } 43 44 func (builder *URLCredentialsProviderBuilder) Build() (provider *URLCredentialsProvider, err error) { 45 46 if builder.provider.url == "" { 47 builder.provider.url = os.Getenv("ALIBABA_CLOUD_CREDENTIALS_URI") 48 } 49 50 if builder.provider.url == "" { 51 err = errors.New("the url is empty") 52 return 53 } 54 55 provider = builder.provider 56 return 57 } 58 59 type urlResponse struct { 60 AccessKeyId *string `json:"AccessKeyId"` 61 AccessKeySecret *string `json:"AccessKeySecret"` 62 SecurityToken *string `json:"SecurityToken"` 63 Expiration *string `json:"Expiration"` 64 } 65 66 func (provider *URLCredentialsProvider) getCredentials() (session *sessionCredentials, err error) { 67 req := &httputil.Request{ 68 Method: "GET", 69 URL: provider.url, 70 } 71 72 connectTimeout := 5 * time.Second 73 readTimeout := 10 * time.Second 74 75 if provider.httpOptions != nil && provider.httpOptions.ConnectTimeout > 0 { 76 connectTimeout = time.Duration(provider.httpOptions.ConnectTimeout) * time.Millisecond 77 } 78 if provider.httpOptions != nil && provider.httpOptions.ReadTimeout > 0 { 79 readTimeout = time.Duration(provider.httpOptions.ReadTimeout) * time.Millisecond 80 } 81 if provider.httpOptions != nil && provider.httpOptions.Proxy != "" { 82 req.Proxy = provider.httpOptions.Proxy 83 } 84 req.ConnectTimeout = connectTimeout 85 req.ReadTimeout = readTimeout 86 87 res, err := httpDo(req) 88 if err != nil { 89 return 90 } 91 92 if res.StatusCode != http.StatusOK { 93 err = fmt.Errorf("get credentials from %s failed: %s", req.BuildRequestURL(), string(res.Body)) 94 return 95 } 96 97 var resp urlResponse 98 err = json.Unmarshal(res.Body, &resp) 99 if err != nil { 100 err = fmt.Errorf("get credentials from %s failed with error, json unmarshal fail: %s", req.BuildRequestURL(), err.Error()) 101 return 102 } 103 104 if resp.AccessKeyId == nil || resp.AccessKeySecret == nil || resp.SecurityToken == nil || resp.Expiration == nil { 105 err = fmt.Errorf("refresh credentials from %s failed: %s", req.BuildRequestURL(), string(res.Body)) 106 return 107 } 108 109 session = &sessionCredentials{ 110 AccessKeyId: *resp.AccessKeyId, 111 AccessKeySecret: *resp.AccessKeySecret, 112 SecurityToken: *resp.SecurityToken, 113 Expiration: *resp.Expiration, 114 } 115 return 116 } 117 118 func (provider *URLCredentialsProvider) needUpdateCredential() (result bool) { 119 if provider.expirationTimestamp == 0 { 120 return true 121 } 122 123 return provider.expirationTimestamp-time.Now().Unix() <= 180 124 } 125 126 func (provider *URLCredentialsProvider) GetCredentials() (cc *Credentials, err error) { 127 if provider.sessionCredentials == nil || provider.needUpdateCredential() { 128 sessionCredentials, err1 := provider.getCredentials() 129 if err1 != nil { 130 return nil, err1 131 } 132 133 provider.sessionCredentials = sessionCredentials 134 expirationTime, err2 := time.Parse("2006-01-02T15:04:05Z", sessionCredentials.Expiration) 135 if err2 != nil { 136 return nil, err2 137 } 138 provider.expirationTimestamp = expirationTime.Unix() 139 } 140 141 cc = &Credentials{ 142 AccessKeyId: provider.sessionCredentials.AccessKeyId, 143 AccessKeySecret: provider.sessionCredentials.AccessKeySecret, 144 SecurityToken: provider.sessionCredentials.SecurityToken, 145 ProviderName: provider.GetProviderName(), 146 } 147 return 148 } 149 150 func (provider *URLCredentialsProvider) GetProviderName() string { 151 return "credential_uri" 152 }