github.com/aliyun/credentials-go@v1.4.7/credentials/ram_role_arn_credentials_provider.go (about) 1 package credentials 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "strconv" 8 "time" 9 10 "github.com/alibabacloud-go/tea/tea" 11 "github.com/aliyun/credentials-go/credentials/internal/utils" 12 "github.com/aliyun/credentials-go/credentials/request" 13 ) 14 15 const defaultDurationSeconds = 3600 16 17 // RAMRoleArnCredentialsProvider is a kind of credentials 18 type RAMRoleArnCredentialsProvider struct { 19 *credentialUpdater 20 AccessKeyId string 21 AccessKeySecret string 22 SecurityToken string 23 RoleArn string 24 RoleSessionName string 25 RoleSessionExpiration int 26 Policy string 27 ExternalId string 28 sessionCredential *sessionCredential 29 runtime *utils.Runtime 30 } 31 32 type ramRoleArnResponse struct { 33 Credentials *credentialsInResponse `json:"Credentials" xml:"Credentials"` 34 } 35 36 type credentialsInResponse struct { 37 AccessKeyId string `json:"AccessKeyId" xml:"AccessKeyId"` 38 AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"` 39 SecurityToken string `json:"SecurityToken" xml:"SecurityToken"` 40 Expiration string `json:"Expiration" xml:"Expiration"` 41 } 42 43 func newRAMRoleArnl(accessKeyId, accessKeySecret, securityToken, roleArn, roleSessionName, policy string, roleSessionExpiration int, externalId string, runtime *utils.Runtime) *RAMRoleArnCredentialsProvider { 44 return &RAMRoleArnCredentialsProvider{ 45 AccessKeyId: accessKeyId, 46 AccessKeySecret: accessKeySecret, 47 SecurityToken: securityToken, 48 RoleArn: roleArn, 49 RoleSessionName: roleSessionName, 50 RoleSessionExpiration: roleSessionExpiration, 51 Policy: policy, 52 ExternalId: externalId, 53 credentialUpdater: new(credentialUpdater), 54 runtime: runtime, 55 } 56 } 57 58 func newRAMRoleArnCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string, roleSessionExpiration int, runtime *utils.Runtime) *RAMRoleArnCredentialsProvider { 59 return &RAMRoleArnCredentialsProvider{ 60 AccessKeyId: accessKeyId, 61 AccessKeySecret: accessKeySecret, 62 RoleArn: roleArn, 63 RoleSessionName: roleSessionName, 64 RoleSessionExpiration: roleSessionExpiration, 65 Policy: policy, 66 credentialUpdater: new(credentialUpdater), 67 runtime: runtime, 68 } 69 } 70 71 func newRAMRoleArnWithExternalIdCredential(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy string, roleSessionExpiration int, externalId string, runtime *utils.Runtime) *RAMRoleArnCredentialsProvider { 72 return &RAMRoleArnCredentialsProvider{ 73 AccessKeyId: accessKeyId, 74 AccessKeySecret: accessKeySecret, 75 RoleArn: roleArn, 76 RoleSessionName: roleSessionName, 77 RoleSessionExpiration: roleSessionExpiration, 78 Policy: policy, 79 ExternalId: externalId, 80 credentialUpdater: new(credentialUpdater), 81 runtime: runtime, 82 } 83 } 84 85 func (e *RAMRoleArnCredentialsProvider) GetCredential() (*CredentialModel, error) { 86 if e.sessionCredential == nil || e.needUpdateCredential() { 87 err := e.updateCredential() 88 if err != nil { 89 return nil, err 90 } 91 } 92 credential := &CredentialModel{ 93 AccessKeyId: tea.String(e.sessionCredential.AccessKeyId), 94 AccessKeySecret: tea.String(e.sessionCredential.AccessKeySecret), 95 SecurityToken: tea.String(e.sessionCredential.SecurityToken), 96 Type: tea.String("ram_role_arn"), 97 } 98 return credential, nil 99 } 100 101 // GetAccessKeyId reutrns RAMRoleArnCredentialsProvider's AccessKeyId 102 // if AccessKeyId is not exist or out of date, the function will update it. 103 func (r *RAMRoleArnCredentialsProvider) GetAccessKeyId() (accessKeyId *string, err error) { 104 c, err := r.GetCredential() 105 if err != nil { 106 return 107 } 108 109 accessKeyId = c.AccessKeyId 110 return 111 } 112 113 // GetAccessSecret reutrns RAMRoleArnCredentialsProvider's AccessKeySecret 114 // if AccessKeySecret is not exist or out of date, the function will update it. 115 func (r *RAMRoleArnCredentialsProvider) GetAccessKeySecret() (accessKeySecret *string, err error) { 116 c, err := r.GetCredential() 117 if err != nil { 118 return 119 } 120 121 accessKeySecret = c.AccessKeySecret 122 return 123 } 124 125 // GetSecurityToken reutrns RAMRoleArnCredentialsProvider's SecurityToken 126 // if SecurityToken is not exist or out of date, the function will update it. 127 func (r *RAMRoleArnCredentialsProvider) GetSecurityToken() (securityToken *string, err error) { 128 c, err := r.GetCredential() 129 if err != nil { 130 return 131 } 132 133 securityToken = c.SecurityToken 134 return 135 } 136 137 // GetBearerToken is useless RAMRoleArnCredentialsProvider 138 func (r *RAMRoleArnCredentialsProvider) GetBearerToken() *string { 139 return tea.String("") 140 } 141 142 // GetType reutrns RAMRoleArnCredentialsProvider's type 143 func (r *RAMRoleArnCredentialsProvider) GetType() *string { 144 return tea.String("ram_role_arn") 145 } 146 147 func (r *RAMRoleArnCredentialsProvider) updateCredential() (err error) { 148 if r.runtime == nil { 149 r.runtime = new(utils.Runtime) 150 } 151 request := request.NewCommonRequest() 152 request.Domain = "sts.aliyuncs.com" 153 if r.runtime.STSEndpoint != "" { 154 request.Domain = r.runtime.STSEndpoint 155 } 156 request.Scheme = "HTTPS" 157 request.Method = "GET" 158 request.QueryParams["AccessKeyId"] = r.AccessKeyId 159 if r.SecurityToken != "" { 160 request.QueryParams["SecurityToken"] = r.SecurityToken 161 } 162 request.QueryParams["Action"] = "AssumeRole" 163 request.QueryParams["Format"] = "JSON" 164 if r.RoleSessionExpiration > 0 { 165 if r.RoleSessionExpiration >= 900 && r.RoleSessionExpiration <= 3600 { 166 request.QueryParams["DurationSeconds"] = strconv.Itoa(r.RoleSessionExpiration) 167 } else { 168 err = errors.New("[InvalidParam]:Assume Role session duration should be in the range of 15min - 1Hr") 169 return 170 } 171 } else { 172 request.QueryParams["DurationSeconds"] = strconv.Itoa(defaultDurationSeconds) 173 } 174 request.QueryParams["RoleArn"] = r.RoleArn 175 if r.Policy != "" { 176 request.QueryParams["Policy"] = r.Policy 177 } 178 if r.ExternalId != "" { 179 request.QueryParams["ExternalId"] = r.ExternalId 180 } 181 request.QueryParams["RoleSessionName"] = r.RoleSessionName 182 request.QueryParams["SignatureMethod"] = "HMAC-SHA1" 183 request.QueryParams["SignatureVersion"] = "1.0" 184 request.QueryParams["Version"] = "2015-04-01" 185 request.QueryParams["Timestamp"] = utils.GetTimeInFormatISO8601() 186 request.QueryParams["SignatureNonce"] = utils.GetUUID() 187 signature := utils.ShaHmac1(request.BuildStringToSign(), r.AccessKeySecret+"&") 188 request.QueryParams["Signature"] = signature 189 request.Headers["Host"] = request.Domain 190 request.Headers["Accept-Encoding"] = "identity" 191 request.URL = request.BuildURL() 192 content, err := doAction(request, r.runtime) 193 if err != nil { 194 return fmt.Errorf("refresh RoleArn sts token err: %s", err.Error()) 195 } 196 var resp *ramRoleArnResponse 197 err = json.Unmarshal(content, &resp) 198 if err != nil { 199 return fmt.Errorf("refresh RoleArn sts token err: Json.Unmarshal fail: %s", err.Error()) 200 } 201 if resp == nil || resp.Credentials == nil { 202 return fmt.Errorf("refresh RoleArn sts token err: Credentials is empty") 203 } 204 respCredentials := resp.Credentials 205 if respCredentials.AccessKeyId == "" || respCredentials.AccessKeySecret == "" || respCredentials.SecurityToken == "" || respCredentials.Expiration == "" { 206 return fmt.Errorf("refresh RoleArn sts token err: AccessKeyId: %s, AccessKeySecret: %s, SecurityToken: %s, Expiration: %s", respCredentials.AccessKeyId, respCredentials.AccessKeySecret, respCredentials.SecurityToken, respCredentials.Expiration) 207 } 208 209 expirationTime, err := time.Parse("2006-01-02T15:04:05Z", respCredentials.Expiration) 210 r.lastUpdateTimestamp = time.Now().Unix() 211 r.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix()) 212 r.sessionCredential = &sessionCredential{ 213 AccessKeyId: respCredentials.AccessKeyId, 214 AccessKeySecret: respCredentials.AccessKeySecret, 215 SecurityToken: respCredentials.SecurityToken, 216 } 217 218 return 219 }