signer_sts_assume_role.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Licensed under the Apache License, Version 2.0 (the "License");
  3. * you may not use this file except in compliance with the License.
  4. * You may obtain a copy of the License at
  5. *
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. */
  14. package signers
  15. import (
  16. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
  17. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
  18. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
  19. "time"
  20. "strconv"
  21. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
  22. "net/http"
  23. "encoding/json"
  24. "github.com/jmespath/go-jmespath"
  25. )
  26. const (
  27. defaultDurationSeconds = 3600
  28. )
  29. type SignerStsAssumeRole struct {
  30. *credentialUpdater
  31. roleSessionName string
  32. sessionCredential *sessionCredential
  33. credential *credentials.StsAssumeRoleCredential
  34. }
  35. type sessionCredential struct {
  36. accessKeyId string
  37. accessKeySecret string
  38. securityToken string
  39. }
  40. func NewSignerStsAssumeRole(credential *credentials.StsAssumeRoleCredential, commonApi func(request *requests.CommonRequest) (response *responses.CommonResponse, err error)) (signer *SignerStsAssumeRole, err error) {
  41. signer = &SignerStsAssumeRole{
  42. credentialUpdater: &credentialUpdater{
  43. credentialExpiration: credential.RoleSessionExpiration,
  44. buildRequestMethod: signer.buildCommonRequest,
  45. responseCallBack: signer.refreshCredential,
  46. commonApi: commonApi,
  47. },
  48. credential: credential,
  49. }
  50. if len(credential.RoleSessionName) > 0 {
  51. signer.roleSessionName = credential.RoleSessionName
  52. } else {
  53. signer.roleSessionName = "aliyun-go-sdk-" + strconv.FormatInt(time.Now().UnixNano()/1000, 10)
  54. }
  55. if credential.RoleSessionExpiration > 0 {
  56. if credential.RoleSessionExpiration > 900 && credential.RoleSessionExpiration < 3600 {
  57. signer.credentialExpiration = credential.RoleSessionExpiration
  58. } else {
  59. err = errors.NewClientError(errors.InvalidParamCode, "Assume Role session duration should be in the range of 15min - 1Hr", nil)
  60. }
  61. } else {
  62. signer.credentialExpiration = defaultDurationSeconds
  63. }
  64. return
  65. }
  66. func (*SignerStsAssumeRole) GetName() string {
  67. return "HMAC-SHA1"
  68. }
  69. func (*SignerStsAssumeRole) GetType() string {
  70. return ""
  71. }
  72. func (*SignerStsAssumeRole) GetVersion() string {
  73. return "1.0"
  74. }
  75. func (signer *SignerStsAssumeRole) GetAccessKeyId() string {
  76. return signer.credential.AccessKeyId
  77. }
  78. func (signer *SignerStsAssumeRole) GetExtraParam() map[string]string {
  79. return map[string]string{"SecurityToken": signer.credential.RoleArn}
  80. }
  81. func (signer *SignerStsAssumeRole) Sign(stringToSign, secretSuffix string) string {
  82. if signer.sessionCredential == nil || signer.needUpdateCredential() {
  83. signer.updateCredential()
  84. }
  85. secret := signer.credential.AccessKeySecret + secretSuffix
  86. return ShaHmac1(stringToSign, secret)
  87. }
  88. func (signer *SignerStsAssumeRole) buildCommonRequest() (request *requests.CommonRequest, err error) {
  89. request = requests.NewCommonRequest()
  90. request.Product = "Sts"
  91. request.Version = "2015-04-01"
  92. request.ApiName = "AssumeRole"
  93. request.QueryParams["RoleArn"] = signer.credential.RoleArn
  94. request.QueryParams["RoleSessionName"] = signer.credential.RoleSessionName
  95. request.QueryParams["DurationSeconds"] = strconv.Itoa(signer.credentialExpiration)
  96. return
  97. }
  98. func (signer *SignerStsAssumeRole) refreshCredential(response *responses.CommonResponse) (err error) {
  99. if response.GetHttpStatus() != http.StatusOK {
  100. message := "refresh session token failed, message = " + response.GetHttpContentString()
  101. err = errors.NewServerError(response.GetHttpStatus(), response.GetOriginHttpResponse().Status, message)
  102. return
  103. }
  104. var data interface{}
  105. err = json.Unmarshal(response.GetHttpContentBytes(), data)
  106. if err != nil {
  107. return
  108. }
  109. accessKeyId, err := jmespath.Search("AssumeRoleResponse.Credentials.AccessKeyId", data)
  110. if err != nil {
  111. return
  112. }
  113. accessKeySecret, err := jmespath.Search("AssumeRoleResponse.Credentials.AccessKeySecret", data)
  114. if err != nil {
  115. return
  116. }
  117. securityToken, err := jmespath.Search("AssumeRoleResponse.Credentials.SecurityToken", data)
  118. if err != nil {
  119. return
  120. }
  121. signer.sessionCredential = &sessionCredential{
  122. accessKeyId: accessKeyId.(string),
  123. accessKeySecret: accessKeySecret.(string),
  124. securityToken: securityToken.(string),
  125. }
  126. return
  127. }
  128. func (signer *SignerStsAssumeRole) Shutdown() {
  129. }