ram_role_arn_credentials_provider.go raw

   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  }
 220