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