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  }