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