1package v2
2
3import (
4	"bytes"
5	"net/http"
6	"net/url"
7	"os"
8	"strconv"
9	"testing"
10	"time"
11
12	"github.com/aws/aws-sdk-go/aws"
13	"github.com/aws/aws-sdk-go/aws/credentials"
14	"github.com/aws/aws-sdk-go/aws/request"
15	"github.com/aws/aws-sdk-go/awstesting"
16)
17
18type signerBuilder struct {
19	ServiceName  string
20	Region       string
21	SignTime     time.Time
22	Query        url.Values
23	Method       string
24	SessionToken string
25}
26
27func (sb signerBuilder) BuildSigner() signer {
28	endpoint := "https://" + sb.ServiceName + "." + sb.Region + ".amazonaws.com"
29	var req *http.Request
30	if sb.Method == "POST" {
31		body := []byte(sb.Query.Encode())
32		reader := bytes.NewReader(body)
33		req, _ = http.NewRequest(sb.Method, endpoint, reader)
34		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
35		req.Header.Add("Content-Length", strconv.Itoa(len(body)))
36	} else {
37		req, _ = http.NewRequest(sb.Method, endpoint, nil)
38		req.URL.RawQuery = sb.Query.Encode()
39	}
40
41	sig := signer{
42		Request: req,
43		Time:    sb.SignTime,
44		Credentials: credentials.NewStaticCredentials(
45			"AKID",
46			"SECRET",
47			sb.SessionToken),
48	}
49
50	if os.Getenv("DEBUG") != "" {
51		sig.Debug = aws.LogDebug
52		sig.Logger = aws.NewDefaultLogger()
53	}
54
55	return sig
56}
57
58func TestSignRequestWithAndWithoutSession(t *testing.T) {
59	// have to create more than once, so use a function
60	newQuery := func() url.Values {
61		query := make(url.Values)
62		query.Add("Action", "CreateDomain")
63		query.Add("DomainName", "TestDomain-1437033376")
64		query.Add("Version", "2009-04-15")
65		return query
66	}
67
68	// create request without a SecurityToken (session) in the credentials
69
70	query := newQuery()
71	timestamp := time.Date(2015, 7, 16, 7, 56, 16, 0, time.UTC)
72	builder := signerBuilder{
73		Method:      "POST",
74		ServiceName: "sdb",
75		Region:      "ap-southeast-2",
76		SignTime:    timestamp,
77		Query:       query,
78	}
79
80	signer := builder.BuildSigner()
81
82	err := signer.Sign()
83	if err != nil {
84		t.Fatalf("expect no error, got %v", err)
85	}
86	if e, a := "tm4dX8Ks7pzFSVHz7qHdoJVXKRLuC4gWz9eti60d8ks=", signer.signature; e != a {
87		t.Errorf("expect %v, got %v", e, a)
88	}
89	if e, a := 8, len(signer.Query); e != a {
90		t.Errorf("expect %v, got %v", e, a)
91	}
92	if e, a := "AKID", signer.Query.Get("AWSAccessKeyId"); e != a {
93		t.Errorf("expect %v, got %v", e, a)
94	}
95	if e, a := "2015-07-16T07:56:16Z", signer.Query.Get("Timestamp"); e != a {
96		t.Errorf("expect %v, got %v", e, a)
97	}
98	if e, a := "HmacSHA256", signer.Query.Get("SignatureMethod"); e != a {
99		t.Errorf("expect %v, got %v", e, a)
100	}
101	if e, a := "2", signer.Query.Get("SignatureVersion"); e != a {
102		t.Errorf("expect %v, got %v", e, a)
103	}
104	if e, a := "tm4dX8Ks7pzFSVHz7qHdoJVXKRLuC4gWz9eti60d8ks=", signer.Query.Get("Signature"); e != a {
105		t.Errorf("expect %v, got %v", e, a)
106	}
107	if e, a := "CreateDomain", signer.Query.Get("Action"); e != a {
108		t.Errorf("expect %v, got %v", e, a)
109	}
110	if e, a := "TestDomain-1437033376", signer.Query.Get("DomainName"); e != a {
111		t.Errorf("expect %v, got %v", e, a)
112	}
113	if e, a := "2009-04-15", signer.Query.Get("Version"); e != a {
114		t.Errorf("expect %v, got %v", e, a)
115	}
116
117	// should not have a SecurityToken parameter
118	_, ok := signer.Query["SecurityToken"]
119	if ok {
120		t.Errorf("expect SecurityToken found, was not")
121	}
122
123	// now sign again, this time with a security token (session)
124
125	query = newQuery()
126	builder.SessionToken = "SESSION"
127	signer = builder.BuildSigner()
128
129	err = signer.Sign()
130	if err != nil {
131		t.Fatalf("expect no error, got %v", err)
132	}
133	if e, a := "Ch6qv3rzXB1SLqY2vFhsgA1WQ9rnQIE2WJCigOvAJwI=", signer.signature; e != a {
134		t.Errorf("expect %v, got %v", e, a)
135	}
136	if e, a := 9, len(signer.Query); e != a { // expect one more parameter
137		t.Errorf("expect %v, got %v", e, a)
138	}
139	if e, a := "Ch6qv3rzXB1SLqY2vFhsgA1WQ9rnQIE2WJCigOvAJwI=", signer.Query.Get("Signature"); e != a {
140		t.Errorf("expect %v, got %v", e, a)
141	}
142	if e, a := "SESSION", signer.Query.Get("SecurityToken"); e != a {
143		t.Errorf("expect %v, got %v", e, a)
144	}
145}
146
147func TestMoreComplexSignRequest(t *testing.T) {
148	query := make(url.Values)
149	query.Add("Action", "PutAttributes")
150	query.Add("DomainName", "TestDomain-1437041569")
151	query.Add("Version", "2009-04-15")
152	query.Add("Attribute.2.Name", "Attr2")
153	query.Add("Attribute.2.Value", "Value2")
154	query.Add("Attribute.2.Replace", "true")
155	query.Add("Attribute.1.Name", "Attr1-%\\+ %")
156	query.Add("Attribute.1.Value", " \tValue1 +!@#$%^&*(){}[]\"';:?/.>,<\x12\x00")
157	query.Add("Attribute.1.Replace", "true")
158	query.Add("ItemName", "Item 1")
159
160	timestamp := time.Date(2015, 7, 16, 10, 12, 51, 0, time.UTC)
161	builder := signerBuilder{
162		Method:       "POST",
163		ServiceName:  "sdb",
164		Region:       "ap-southeast-2",
165		SignTime:     timestamp,
166		Query:        query,
167		SessionToken: "SESSION",
168	}
169
170	signer := builder.BuildSigner()
171
172	err := signer.Sign()
173	if err != nil {
174		t.Fatalf("expect no error, got %v", err)
175	}
176	if e, a := "WNdE62UJKLKoA6XncVY/9RDbrKmcVMdQPQOTAs8SgwQ=", signer.signature; e != a {
177		t.Errorf("expect %v, got %v", e, a)
178	}
179}
180
181func TestGet(t *testing.T) {
182	svc := awstesting.NewClient(&aws.Config{
183		Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
184		Region:      aws.String("ap-southeast-2"),
185	})
186	r := svc.NewRequest(
187		&request.Operation{
188			Name:       "OpName",
189			HTTPMethod: "GET",
190			HTTPPath:   "/",
191		},
192		nil,
193		nil,
194	)
195
196	r.Build()
197	if e, a := "GET", r.HTTPRequest.Method; e != a {
198		t.Errorf("expect %v, got %v", e, a)
199	}
200	if e, a := "", r.HTTPRequest.URL.Query().Get("Signature"); e != a {
201		t.Errorf("expect %v, got %v", e, a)
202	}
203
204	SignSDKRequest(r)
205	if r.Error != nil {
206		t.Fatalf("expect no error, got %v", r.Error)
207	}
208	t.Logf("Signature: %s", r.HTTPRequest.URL.Query().Get("Signature"))
209	if len(r.HTTPRequest.URL.Query().Get("Signature")) == 0 {
210		t.Errorf("expect signature to be set, was not")
211	}
212}
213
214func TestAnonymousCredentials(t *testing.T) {
215	svc := awstesting.NewClient(&aws.Config{
216		Credentials: credentials.AnonymousCredentials,
217		Region:      aws.String("ap-southeast-2"),
218	})
219	r := svc.NewRequest(
220		&request.Operation{
221			Name:       "PutAttributes",
222			HTTPMethod: "POST",
223			HTTPPath:   "/",
224		},
225		nil,
226		nil,
227	)
228	r.Build()
229
230	SignSDKRequest(r)
231
232	req := r.HTTPRequest
233	req.ParseForm()
234
235	if a := req.PostForm.Get("Signature"); len(a) != 0 {
236		t.Errorf("expect no signature, got %v", a)
237	}
238}
239