• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *    * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *    * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *
15  *    * Neither the name of Google LLC nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package com.google.auth.oauth2;
33 
34 import static org.junit.Assert.assertEquals;
35 
36 import com.google.api.client.json.GenericJson;
37 import com.google.api.client.json.JsonFactory;
38 import com.google.api.client.json.JsonObjectParser;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.net.URI;
42 import java.nio.charset.StandardCharsets;
43 import java.util.HashMap;
44 import java.util.Locale;
45 import java.util.Map;
46 import org.junit.Before;
47 import org.junit.Test;
48 
49 /**
50  * Tests for {@link AwsRequestSigner}.
51  *
52  * <p>Examples of sigv4 signed requests:
53  * https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
54  */
55 public class AwsRequestSignerTest {
56 
57   private static final String DATE = "Mon, 09 Sep 2011 23:36:00 GMT";
58   private static final String X_AMZ_DATE = "20200811T065522Z";
59 
60   private static final AwsSecurityCredentials BOTOCORE_CREDENTIALS =
61       new AwsSecurityCredentials(
62           "AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", /* token= */ null);
63 
64   private AwsSecurityCredentials awsSecurityCredentials;
65 
66   @Before
setUp()67   public void setUp() throws IOException {
68     // Required for date parsing when run in different Locales
69     Locale.setDefault(Locale.US);
70     awsSecurityCredentials = retrieveAwsSecurityCredentials();
71   }
72 
73   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-vanilla.req
74   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-vanilla.sreq
75   @Test
sign_getHost()76   public void sign_getHost() {
77     String url = "https://host.foo.com";
78 
79     Map<String, String> headers = new HashMap<>();
80     headers.put("date", DATE);
81 
82     AwsRequestSigner signer =
83         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
84             .setAdditionalHeaders(headers)
85             .build();
86 
87     AwsRequestSignature signature = signer.sign();
88 
89     String expectedSignature = "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470";
90     String expectedAuthHeader =
91         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
92             + "aws4_request, SignedHeaders=date;host, Signature="
93             + expectedSignature;
94 
95     assertEquals(expectedSignature, signature.getSignature());
96     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
97     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
98     assertEquals(DATE, signature.getDate());
99     assertEquals("GET", signature.getHttpMethod());
100     assertEquals("us-east-1", signature.getRegion());
101     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
102   }
103 
104   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-relative-relative.req
105   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-relative-relative.sreq
106   @Test
sign_getHostRelativePath()107   public void sign_getHostRelativePath() {
108     String url = "https://host.foo.com/foo/bar/../..";
109 
110     Map<String, String> headers = new HashMap<>();
111     headers.put("date", DATE);
112 
113     AwsRequestSigner signer =
114         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
115             .setAdditionalHeaders(headers)
116             .build();
117 
118     AwsRequestSignature signature = signer.sign();
119 
120     String expectedSignature = "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470";
121     String expectedAuthHeader =
122         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
123             + "aws4_request, SignedHeaders=date;host, Signature="
124             + expectedSignature;
125 
126     assertEquals(expectedSignature, signature.getSignature());
127     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
128     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
129     assertEquals(DATE, signature.getDate());
130     assertEquals("GET", signature.getHttpMethod());
131     assertEquals("us-east-1", signature.getRegion());
132     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
133   }
134 
135   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-slash-dot-slash.req
136   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-slash-dot-slash.sreq
137   @Test
sign_getHostInvalidPath()138   public void sign_getHostInvalidPath() {
139     String url = "https://host.foo.com/./";
140 
141     Map<String, String> headers = new HashMap<>();
142     headers.put("date", DATE);
143 
144     AwsRequestSigner signer =
145         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
146             .setAdditionalHeaders(headers)
147             .build();
148 
149     AwsRequestSignature signature = signer.sign();
150 
151     String expectedSignature = "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470";
152     String expectedAuthHeader =
153         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
154             + "aws4_request, SignedHeaders=date;host, Signature="
155             + expectedSignature;
156 
157     assertEquals(expectedSignature, signature.getSignature());
158     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
159     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
160     assertEquals(DATE, signature.getDate());
161     assertEquals("GET", signature.getHttpMethod());
162     assertEquals("us-east-1", signature.getRegion());
163     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
164   }
165 
166   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-slash-pointless-dot.req
167   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-slash-pointless-dot.sreq
168   @Test
sign_getHostDotPath()169   public void sign_getHostDotPath() {
170     String url = "https://host.foo.com/./foo";
171 
172     Map<String, String> headers = new HashMap<>();
173     headers.put("date", DATE);
174 
175     AwsRequestSigner signer =
176         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
177             .setAdditionalHeaders(headers)
178             .build();
179 
180     AwsRequestSignature signature = signer.sign();
181 
182     String expectedSignature = "910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a";
183     String expectedAuthHeader =
184         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
185             + "aws4_request, SignedHeaders=date;host, Signature="
186             + expectedSignature;
187 
188     assertEquals(expectedSignature, signature.getSignature());
189     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
190     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
191     assertEquals(DATE, signature.getDate());
192     assertEquals("GET", signature.getHttpMethod());
193     assertEquals("us-east-1", signature.getRegion());
194     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
195   }
196 
197   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-utf8.req
198   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-utf8.sreq
199   @Test
sign_getHostUtf8Path()200   public void sign_getHostUtf8Path() {
201     String url = "https://host.foo.com/%E1%88%B4";
202 
203     Map<String, String> headers = new HashMap<>();
204     headers.put("date", DATE);
205 
206     AwsRequestSigner signer =
207         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
208             .setAdditionalHeaders(headers)
209             .build();
210 
211     AwsRequestSignature signature = signer.sign();
212 
213     String expectedSignature = "8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74";
214     String expectedAuthHeader =
215         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
216             + "aws4_request, SignedHeaders=date;host, Signature="
217             + expectedSignature;
218 
219     assertEquals(expectedSignature, signature.getSignature());
220     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
221     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
222     assertEquals(DATE, signature.getDate());
223     assertEquals("GET", signature.getHttpMethod());
224     assertEquals("us-east-1", signature.getRegion());
225     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
226   }
227 
228   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-vanilla-query-order-key-case.req
229   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-vanilla-query-order-key-case.sreq
230   @Test
sign_getHostDuplicateQueryParam()231   public void sign_getHostDuplicateQueryParam() {
232     String url = "https://host.foo.com/?foo=Zoo&foo=aha";
233 
234     Map<String, String> headers = new HashMap<>();
235     headers.put("date", DATE);
236 
237     AwsRequestSigner signer =
238         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "GET", url, "us-east-1")
239             .setAdditionalHeaders(headers)
240             .build();
241 
242     AwsRequestSignature signature = signer.sign();
243 
244     String expectedSignature = "be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09";
245     String expectedAuthHeader =
246         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
247             + "aws4_request, SignedHeaders=date;host, Signature="
248             + expectedSignature;
249 
250     assertEquals(expectedSignature, signature.getSignature());
251     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
252     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
253     assertEquals(DATE, signature.getDate());
254     assertEquals("GET", signature.getHttpMethod());
255     assertEquals("us-east-1", signature.getRegion());
256     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
257   }
258 
259   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-header-key-sort.req
260   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-header-key-sort.sreq
261   @Test
sign_postWithUpperCaseHeaderKey()262   public void sign_postWithUpperCaseHeaderKey() {
263     String url = "https://host.foo.com/";
264     String headerKey = "ZOO";
265     String headerValue = "zoobar";
266 
267     Map<String, String> headers = new HashMap<>();
268     headers.put("date", DATE);
269     headers.put(headerKey, headerValue);
270 
271     AwsRequestSigner signer =
272         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "POST", url, "us-east-1")
273             .setAdditionalHeaders(headers)
274             .build();
275 
276     AwsRequestSignature signature = signer.sign();
277 
278     String expectedSignature = "b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a";
279     String expectedAuthHeader =
280         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
281             + "aws4_request, SignedHeaders=date;host;zoo, Signature="
282             + expectedSignature;
283 
284     assertEquals(expectedSignature, signature.getSignature());
285     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
286     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
287     assertEquals(DATE, signature.getDate());
288     assertEquals("POST", signature.getHttpMethod());
289     assertEquals("us-east-1", signature.getRegion());
290     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
291     assertEquals(headerValue, signature.getCanonicalHeaders().get(headerKey.toLowerCase()));
292   }
293 
294   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-header-value-case.req
295   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-header-value-case.sreq
296   @Test
sign_postWithUpperCaseHeaderValue()297   public void sign_postWithUpperCaseHeaderValue() {
298     String url = "https://host.foo.com/";
299     String headerKey = "zoo";
300     String headerValue = "ZOOBAR";
301 
302     Map<String, String> headers = new HashMap<>();
303     headers.put("date", DATE);
304     headers.put("zoo", "ZOOBAR");
305 
306     AwsRequestSigner signer =
307         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "POST", url, "us-east-1")
308             .setAdditionalHeaders(headers)
309             .build();
310 
311     AwsRequestSignature signature = signer.sign();
312 
313     String expectedSignature = "273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7";
314     String expectedAuthHeader =
315         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
316             + "aws4_request, SignedHeaders=date;host;zoo, Signature="
317             + expectedSignature;
318 
319     assertEquals(expectedSignature, signature.getSignature());
320     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
321     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
322     assertEquals(DATE, signature.getDate());
323     assertEquals("POST", signature.getHttpMethod());
324     assertEquals("us-east-1", signature.getRegion());
325     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
326     assertEquals(headerValue, signature.getCanonicalHeaders().get(headerKey.toLowerCase()));
327   }
328 
329   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-header-value-trim.req
330   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-header-value-trim.sreq
331   @Test
sign_postWithHeader()332   public void sign_postWithHeader() {
333     String url = "https://host.foo.com/";
334     String headerKey = "p";
335     String headerValue = "phfft";
336 
337     Map<String, String> headers = new HashMap<>();
338     headers.put("date", DATE);
339     headers.put(headerKey, headerValue);
340 
341     AwsRequestSigner signer =
342         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "POST", url, "us-east-1")
343             .setAdditionalHeaders(headers)
344             .build();
345 
346     AwsRequestSignature signature = signer.sign();
347 
348     String expectedSignature = "debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592";
349     String expectedAuthHeader =
350         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
351             + "aws4_request, SignedHeaders=date;host;p, Signature="
352             + expectedSignature;
353 
354     assertEquals(expectedSignature, signature.getSignature());
355     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
356     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
357     assertEquals(DATE, signature.getDate());
358     assertEquals("POST", signature.getHttpMethod());
359     assertEquals("us-east-1", signature.getRegion());
360     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
361     assertEquals(headerValue, signature.getCanonicalHeaders().get(headerKey.toLowerCase()));
362   }
363 
364   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-x-www-form-urlencoded.req
365   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-x-www-form-urlencoded.sreq
366   @Test
sign_postWithBodyNoCustomHeaders()367   public void sign_postWithBodyNoCustomHeaders() {
368     String url = "https://host.foo.com/";
369     String headerKey = "Content-Type";
370     String headerValue = "application/x-www-form-urlencoded";
371 
372     Map<String, String> headers = new HashMap<>();
373     headers.put("date", DATE);
374     headers.put(headerKey, headerValue);
375 
376     AwsRequestSigner signer =
377         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "POST", url, "us-east-1")
378             .setAdditionalHeaders(headers)
379             .setRequestPayload("foo=bar")
380             .build();
381 
382     AwsRequestSignature signature = signer.sign();
383 
384     String expectedSignature = "5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc";
385     String expectedAuthHeader =
386         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
387             + "aws4_request, SignedHeaders=content-type;date;host, Signature="
388             + expectedSignature;
389 
390     assertEquals(expectedSignature, signature.getSignature());
391     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
392     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
393     assertEquals(DATE, signature.getDate());
394     assertEquals("POST", signature.getHttpMethod());
395     assertEquals("us-east-1", signature.getRegion());
396     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
397     assertEquals(headerValue, signature.getCanonicalHeaders().get(headerKey.toLowerCase()));
398   }
399 
400   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-vanilla-query.req
401   // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/post-vanilla-query.sreq
402   @Test
sign_postWithQueryString()403   public void sign_postWithQueryString() {
404     String url = "https://host.foo.com/?foo=bar";
405 
406     Map<String, String> headers = new HashMap<>();
407     headers.put("date", DATE);
408 
409     AwsRequestSigner signer =
410         AwsRequestSigner.newBuilder(BOTOCORE_CREDENTIALS, "POST", url, "us-east-1")
411             .setAdditionalHeaders(headers)
412             .build();
413 
414     AwsRequestSignature signature = signer.sign();
415 
416     String expectedSignature = "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92";
417     String expectedAuthHeader =
418         "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/"
419             + "aws4_request, SignedHeaders=date;host, Signature="
420             + expectedSignature;
421 
422     assertEquals(expectedSignature, signature.getSignature());
423     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
424     assertEquals(BOTOCORE_CREDENTIALS, signature.getSecurityCredentials());
425     assertEquals(DATE, signature.getDate());
426     assertEquals("POST", signature.getHttpMethod());
427     assertEquals("us-east-1", signature.getRegion());
428     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
429   }
430 
431   @Test
sign_getDescribeRegions()432   public void sign_getDescribeRegions() {
433     String url = "https://ec2.us-east-2.amazonaws.com?Action=DescribeRegions&Version=2013-10-15";
434 
435     Map<String, String> additionalHeaders = new HashMap<>();
436     additionalHeaders.put("x-amz-date", X_AMZ_DATE);
437 
438     AwsRequestSigner signer =
439         AwsRequestSigner.newBuilder(awsSecurityCredentials, "GET", url, "us-east-2")
440             .setAdditionalHeaders(additionalHeaders)
441             .build();
442 
443     AwsRequestSignature signature = signer.sign();
444 
445     String expectedSignature = "631ea80cddfaa545fdadb120dc92c9f18166e38a5c47b50fab9fce476e022855";
446     String expectedAuthHeader =
447         "AWS4-HMAC-SHA256 Credential="
448             + awsSecurityCredentials.getAccessKeyId()
449             + "/20200811/us-east-2/ec2/"
450             + "aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature="
451             + expectedSignature;
452 
453     assertEquals(expectedSignature, signature.getSignature());
454     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
455     assertEquals(awsSecurityCredentials, signature.getSecurityCredentials());
456     assertEquals(X_AMZ_DATE, signature.getDate());
457     assertEquals("GET", signature.getHttpMethod());
458     assertEquals("us-east-2", signature.getRegion());
459     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
460   }
461 
462   @Test
sign_postGetCallerIdentity()463   public void sign_postGetCallerIdentity() {
464     String url = "https://sts.us-east-2.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15";
465 
466     Map<String, String> additionalHeaders = new HashMap<>();
467     additionalHeaders.put("x-amz-date", X_AMZ_DATE);
468 
469     AwsRequestSigner signer =
470         AwsRequestSigner.newBuilder(awsSecurityCredentials, "POST", url, "us-east-2")
471             .setAdditionalHeaders(additionalHeaders)
472             .build();
473 
474     AwsRequestSignature signature = signer.sign();
475 
476     String expectedSignature = "73452984e4a880ffdc5c392355733ec3f5ba310d5e0609a89244440cadfe7a7a";
477     String expectedAuthHeader =
478         "AWS4-HMAC-SHA256 Credential="
479             + awsSecurityCredentials.getAccessKeyId()
480             + "/20200811/us-east-2/sts/"
481             + "aws4_request, SignedHeaders=host;x-amz-date;x-amz-security-token, Signature="
482             + expectedSignature;
483 
484     assertEquals(expectedSignature, signature.getSignature());
485     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
486     assertEquals(awsSecurityCredentials, signature.getSecurityCredentials());
487     assertEquals(X_AMZ_DATE, signature.getDate());
488     assertEquals("POST", signature.getHttpMethod());
489     assertEquals("us-east-2", signature.getRegion());
490     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
491   }
492 
493   @Test
sign_postGetCallerIdentityNoToken()494   public void sign_postGetCallerIdentityNoToken() {
495     String url = "https://sts.us-east-2.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15";
496 
497     AwsSecurityCredentials awsSecurityCredentialsWithoutToken =
498         new AwsSecurityCredentials(
499             awsSecurityCredentials.getAccessKeyId(),
500             awsSecurityCredentials.getSecretAccessKey(),
501             /* token= */ null);
502 
503     Map<String, String> additionalHeaders = new HashMap<>();
504     additionalHeaders.put("x-amz-date", X_AMZ_DATE);
505 
506     AwsRequestSigner signer =
507         AwsRequestSigner.newBuilder(awsSecurityCredentialsWithoutToken, "POST", url, "us-east-2")
508             .setAdditionalHeaders(additionalHeaders)
509             .build();
510 
511     AwsRequestSignature signature = signer.sign();
512 
513     String expectedSignature = "d095ba304919cd0d5570ba8a3787884ee78b860f268ed040ba23831d55536d56";
514     String expectedAuthHeader =
515         "AWS4-HMAC-SHA256 Credential="
516             + awsSecurityCredentials.getAccessKeyId()
517             + "/20200811/us-east-2/sts/"
518             + "aws4_request, SignedHeaders=host;x-amz-date, Signature="
519             + expectedSignature;
520 
521     assertEquals(expectedSignature, signature.getSignature());
522     assertEquals(expectedAuthHeader, signature.getAuthorizationHeader());
523     assertEquals(awsSecurityCredentialsWithoutToken, signature.getSecurityCredentials());
524     assertEquals(X_AMZ_DATE, signature.getDate());
525     assertEquals("POST", signature.getHttpMethod());
526     assertEquals("us-east-2", signature.getRegion());
527     assertEquals(URI.create(url).normalize().toString(), signature.getUrl());
528   }
529 
retrieveAwsSecurityCredentials()530   public AwsSecurityCredentials retrieveAwsSecurityCredentials() throws IOException {
531     InputStream stream =
532         AwsRequestSignerTest.class
533             .getClassLoader()
534             .getResourceAsStream("aws_security_credentials.json");
535 
536     JsonFactory jsonFactory = OAuth2Utils.JSON_FACTORY;
537     JsonObjectParser parser = new JsonObjectParser(jsonFactory);
538 
539     GenericJson json = parser.parseAndClose(stream, StandardCharsets.UTF_8, GenericJson.class);
540 
541     String accessKeyId = (String) json.get("AccessKeyId");
542     String secretAccessKey = (String) json.get("SecretAccessKey");
543     String awsToken = (String) json.get("Token");
544 
545     return new AwsSecurityCredentials(accessKeyId, secretAccessKey, awsToken);
546   }
547 }
548