...
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
16 type RsaKeyPairCredential struct {
17 *credentialUpdater
18 PrivateKey string
19 PublicKeyId string
20 SessionExpiration int
21 sessionCredential *sessionCredential
22 runtime *utils.Runtime
23 }
24
25 type rsaKeyPairResponse struct {
26 SessionAccessKey *sessionAccessKey `json:"SessionAccessKey" xml:"SessionAccessKey"`
27 }
28
29 type sessionAccessKey struct {
30 SessionAccessKeyId string `json:"SessionAccessKeyId" xml:"SessionAccessKeyId"`
31 SessionAccessKeySecret string `json:"SessionAccessKeySecret" xml:"SessionAccessKeySecret"`
32 Expiration string `json:"Expiration" xml:"Expiration"`
33 }
34
35 func newRsaKeyPairCredential(privateKey, publicKeyId string, sessionExpiration int, runtime *utils.Runtime) *RsaKeyPairCredential {
36 return &RsaKeyPairCredential{
37 PrivateKey: privateKey,
38 PublicKeyId: publicKeyId,
39 SessionExpiration: sessionExpiration,
40 credentialUpdater: new(credentialUpdater),
41 runtime: runtime,
42 }
43 }
44
45 func (e *RsaKeyPairCredential) GetCredential() (*CredentialModel, error) {
46 if e.sessionCredential == nil || e.needUpdateCredential() {
47 err := e.updateCredential()
48 if err != nil {
49 return nil, err
50 }
51 }
52 credential := &CredentialModel{
53 AccessKeyId: tea.String(e.sessionCredential.AccessKeyId),
54 AccessKeySecret: tea.String(e.sessionCredential.AccessKeySecret),
55 SecurityToken: tea.String(e.sessionCredential.SecurityToken),
56 Type: tea.String("rsa_key_pair"),
57 }
58 return credential, nil
59 }
60
61
62
63 func (r *RsaKeyPairCredential) GetAccessKeyId() (*string, error) {
64 if r.sessionCredential == nil || r.needUpdateCredential() {
65 err := r.updateCredential()
66 if err != nil {
67 return tea.String(""), err
68 }
69 }
70 return tea.String(r.sessionCredential.AccessKeyId), nil
71 }
72
73
74
75 func (r *RsaKeyPairCredential) GetAccessKeySecret() (*string, error) {
76 if r.sessionCredential == nil || r.needUpdateCredential() {
77 err := r.updateCredential()
78 if err != nil {
79 return tea.String(""), err
80 }
81 }
82 return tea.String(r.sessionCredential.AccessKeySecret), nil
83 }
84
85
86 func (r *RsaKeyPairCredential) GetSecurityToken() (*string, error) {
87 return tea.String(""), nil
88 }
89
90
91 func (r *RsaKeyPairCredential) GetBearerToken() *string {
92 return tea.String("")
93 }
94
95
96 func (r *RsaKeyPairCredential) GetType() *string {
97 return tea.String("rsa_key_pair")
98 }
99
100 func (r *RsaKeyPairCredential) updateCredential() (err error) {
101 if r.runtime == nil {
102 r.runtime = new(utils.Runtime)
103 }
104 request := request.NewCommonRequest()
105 request.Domain = "sts.aliyuncs.com"
106 if r.runtime.Host != "" {
107 request.Domain = r.runtime.Host
108 } else if r.runtime.STSEndpoint != "" {
109 request.Domain = r.runtime.STSEndpoint
110 }
111 request.Scheme = "HTTPS"
112 request.Method = "GET"
113 request.QueryParams["AccessKeyId"] = r.PublicKeyId
114 request.QueryParams["Action"] = "GenerateSessionAccessKey"
115 request.QueryParams["Format"] = "JSON"
116 if r.SessionExpiration > 0 {
117 if r.SessionExpiration >= 900 && r.SessionExpiration <= 3600 {
118 request.QueryParams["DurationSeconds"] = strconv.Itoa(r.SessionExpiration)
119 } else {
120 err = errors.New("[InvalidParam]:Key Pair session duration should be in the range of 15min - 1Hr")
121 return
122 }
123 } else {
124 request.QueryParams["DurationSeconds"] = strconv.Itoa(defaultDurationSeconds)
125 }
126 request.QueryParams["SignatureMethod"] = "SHA256withRSA"
127 request.QueryParams["SignatureType"] = "PRIVATEKEY"
128 request.QueryParams["SignatureVersion"] = "1.0"
129 request.QueryParams["Version"] = "2015-04-01"
130 request.QueryParams["Timestamp"] = utils.GetTimeInFormatISO8601()
131 request.QueryParams["SignatureNonce"] = utils.GetUUID()
132 signature := utils.Sha256WithRsa(request.BuildStringToSign(), r.PrivateKey)
133 request.QueryParams["Signature"] = signature
134 request.Headers["Host"] = request.Domain
135 request.Headers["Accept-Encoding"] = "identity"
136 request.URL = request.BuildURL()
137 content, err := doAction(request, r.runtime)
138 if err != nil {
139 return fmt.Errorf("refresh KeyPair err: %s", err.Error())
140 }
141 var resp *rsaKeyPairResponse
142 err = json.Unmarshal(content, &resp)
143 if err != nil {
144 return fmt.Errorf("refresh KeyPair err: Json Unmarshal fail: %s", err.Error())
145 }
146 if resp == nil || resp.SessionAccessKey == nil {
147 return fmt.Errorf("refresh KeyPair err: SessionAccessKey is empty")
148 }
149 sessionAccessKey := resp.SessionAccessKey
150 if sessionAccessKey.SessionAccessKeyId == "" || sessionAccessKey.SessionAccessKeySecret == "" || sessionAccessKey.Expiration == "" {
151 return fmt.Errorf("refresh KeyPair err: SessionAccessKeyId: %v, SessionAccessKeySecret: %v, Expiration: %v", sessionAccessKey.SessionAccessKeyId, sessionAccessKey.SessionAccessKeySecret, sessionAccessKey.Expiration)
152 }
153
154 expirationTime, err := time.Parse("2006-01-02T15:04:05Z", sessionAccessKey.Expiration)
155 r.lastUpdateTimestamp = time.Now().Unix()
156 r.credentialExpiration = int(expirationTime.Unix() - time.Now().Unix())
157 r.sessionCredential = &sessionCredential{
158 AccessKeyId: sessionAccessKey.SessionAccessKeyId,
159 AccessKeySecret: sessionAccessKey.SessionAccessKeySecret,
160 }
161
162 return
163 }
164
View as plain text