1package signers
2
3import (
4	"bytes"
5	"fmt"
6	"io/ioutil"
7	"net/http"
8	"strconv"
9	"strings"
10	"testing"
11
12	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
13	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
14	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
15	"github.com/stretchr/testify/assert"
16)
17
18func Test_NewRamRoleArnSigner(t *testing.T) {
19	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3500)
20	signer, err := NewRamRoleArnSigner(c, nil)
21	assert.Nil(t, err)
22	assert.Equal(t, "roleSessionName", signer.roleSessionName)
23	assert.Equal(t, 3500, signer.credentialExpiration)
24
25	assert.Equal(t, "HMAC-SHA1", signer.GetName())
26	assert.Equal(t, "", signer.GetType())
27	assert.Equal(t, "1.0", signer.GetVersion())
28
29	c = credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "", 0)
30	signer, err = NewRamRoleArnSigner(c, nil)
31	assert.Nil(t, err)
32	assert.True(t, strings.HasPrefix(signer.roleSessionName, "aliyun-go-sdk-"))
33	assert.Equal(t, 3600, signer.credentialExpiration)
34
35	c = credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "", 100)
36	signer, err = NewRamRoleArnSigner(c, nil)
37	assert.NotNil(t, err)
38	assert.Equal(t, "[SDK.InvalidParam] Assume Role session duration should be in the range of 15min - 1Hr", err.Error())
39}
40
41func Test_RamRoleArn_buildCommonRequest(t *testing.T) {
42	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
43	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
44		return nil, fmt.Errorf("common api fails")
45	})
46	assert.Nil(t, err)
47	request, err := s.buildCommonRequest()
48	assert.Nil(t, err)
49	assert.NotNil(t, request)
50	assert.Equal(t, "Sts", request.Product)
51	assert.Equal(t, "2015-04-01", request.Version)
52	assert.Equal(t, "AssumeRole", request.ApiName)
53	assert.Equal(t, "HTTPS", request.Scheme)
54	assert.Equal(t, "roleArn", request.QueryParams["RoleArn"])
55	assert.Equal(t, "roleSessionName", request.QueryParams["RoleSessionName"])
56	assert.Equal(t, "3600", request.QueryParams["DurationSeconds"])
57	assert.Nil(t, s.GetSessionCredential())
58}
59
60func Test_RamRoleArn_GetAccessKeyId(t *testing.T) {
61	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
62	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
63		return nil, fmt.Errorf("common api fails")
64	})
65	assert.Nil(t, err)
66	assert.NotNil(t, s)
67	accessKeyId, err := s.GetAccessKeyId()
68	assert.Equal(t, "common api fails", err.Error())
69	assert.Equal(t, "", accessKeyId)
70}
71
72func Test_RamRoleArn_GetAccessKeyId2(t *testing.T) {
73	// default response is not OK
74	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
75	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
76		return responses.NewCommonResponse(), nil
77	})
78	assert.Nil(t, err)
79	assert.NotNil(t, s)
80	// s.lastUpdateTimestamp = time.Now().Unix() - 1000
81	accessKeyId, err := s.GetAccessKeyId()
82	assert.Equal(t, "SDK.ServerError\nErrorCode: \nRecommend: refresh session token failed\nRequestId: \nMessage: ", err.Error())
83	assert.Equal(t, "", accessKeyId)
84}
85
86func Test_RamRoleArn_GetAccessKeyId3(t *testing.T) {
87	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
88	// Mock the 200 response and invalid json
89	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
90		res := responses.NewCommonResponse()
91		statusCode := 200
92		status := strconv.Itoa(statusCode)
93		httpresp := &http.Response{
94			Proto:      "HTTP/1.1",
95			ProtoMajor: 1,
96			Header:     make(http.Header),
97			StatusCode: statusCode,
98			Status:     status + " " + http.StatusText(statusCode),
99		}
100		httpresp.Body = ioutil.NopCloser(bytes.NewReader([]byte("invalid json")))
101		responses.Unmarshal(res, httpresp, "JSON")
102		return res, nil
103	})
104	assert.Nil(t, err)
105	assert.NotNil(t, s)
106	// s.lastUpdateTimestamp = time.Now().Unix() - 1000
107	accessKeyId, err := s.GetAccessKeyId()
108	assert.NotNil(t, err)
109	assert.Equal(t, "refresh RoleArn sts token err, json.Unmarshal fail: invalid character 'i' looking for beginning of value", err.Error())
110	assert.Equal(t, "", accessKeyId)
111}
112
113func Test_RamRoleArn_GetAccessKeyId4(t *testing.T) {
114	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
115	// Mock the 200 response and invalid json
116	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
117		res := responses.NewCommonResponse()
118		statusCode := 200
119		header := make(http.Header)
120		status := strconv.Itoa(statusCode)
121		httpresp := &http.Response{
122			Proto:      "HTTP/1.1",
123			ProtoMajor: 1,
124			Header:     header,
125			StatusCode: statusCode,
126			Status:     status + " " + http.StatusText(statusCode),
127		}
128		httpresp.Header = make(http.Header)
129		httpresp.Body = ioutil.NopCloser(bytes.NewReader([]byte("{}")))
130		responses.Unmarshal(res, httpresp, "JSON")
131		return res, nil
132	})
133	assert.Nil(t, err)
134	assert.NotNil(t, s)
135	// s.lastUpdateTimestamp = time.Now().Unix() - 1000
136	accessKeyId, err := s.GetAccessKeyId()
137	assert.Nil(t, err)
138	assert.Equal(t, "", accessKeyId)
139}
140
141func Test_RamRoleArn_GetAccessKeyIdAndSign(t *testing.T) {
142	c := credentials.NewRamRoleArnCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", 3600)
143	// mock 200 response and valid json and valid result
144	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
145		res := responses.NewCommonResponse()
146		statusCode := 200
147		header := make(http.Header)
148		status := strconv.Itoa(statusCode)
149		httpresp := &http.Response{
150			Proto:      "HTTP/1.1",
151			ProtoMajor: 1,
152			Header:     header,
153			StatusCode: statusCode,
154			Status:     status + " " + http.StatusText(statusCode),
155		}
156
157		json := `{"Credentials":{"AccessKeyId":"access key id","AccessKeySecret": "access key secret","SecurityToken":"security token"}}`
158		httpresp.Body = ioutil.NopCloser(bytes.NewReader([]byte(json)))
159		responses.Unmarshal(res, httpresp, "JSON")
160		return res, nil
161	})
162	assert.Nil(t, err)
163	assert.NotNil(t, s)
164	// s.lastUpdateTimestamp = time.Now().Unix() - 1000
165	accessKeyId, err := s.GetAccessKeyId()
166	assert.Nil(t, err)
167	assert.Equal(t, "access key id", accessKeyId)
168
169	params := s.GetExtraParam()
170	assert.NotNil(t, params)
171	assert.Len(t, params, 1)
172	assert.Equal(t, "security token", params["SecurityToken"])
173	// assert.Nil(t, err)
174	signature := s.Sign("string to sign", "/")
175	assert.Equal(t, "dcM4bWGEoD5QUp9xhLW3SfcWfgs=", signature)
176}
177
178func Test_RamRoleArn_GetExtraParam_Fail(t *testing.T) {
179	c := credentials.NewRamRoleArnWithPolicyCredential("accessKeyId", "accessKeySecret", "roleArn", "roleSessionName", "policy", 3600)
180	// mock 200 response and valid json and valid result
181	s, err := NewRamRoleArnSigner(c, func(*requests.CommonRequest, interface{}) (response *responses.CommonResponse, err error) {
182		res := responses.NewCommonResponse()
183		statusCode := 200
184		header := make(http.Header)
185		status := strconv.Itoa(statusCode)
186		httpresp := &http.Response{
187			Proto:      "HTTP/1.1",
188			ProtoMajor: 1,
189			Header:     header,
190			StatusCode: statusCode,
191			Status:     status + " " + http.StatusText(statusCode),
192		}
193
194		json := `{"Credentials":{"AccessKeyId":"access key id","AccessKeySecret": "access key secret","SecurityToken":""}}`
195		httpresp.Body = ioutil.NopCloser(bytes.NewReader([]byte(json)))
196		responses.Unmarshal(res, httpresp, "JSON")
197		return res, nil
198	})
199	assert.Nil(t, err)
200	assert.NotNil(t, s)
201
202	params := s.GetExtraParam()
203	assert.Len(t, params, 0)
204}
205