uri.go 4.1 KB

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