/* * Copyright (c) 2016. Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.amazonaws.auth; import com.amazonaws.SignableRequest; import com.amazonaws.auth.internal.AWS4SignerUtils; import org.junit.Test; import java.io.ByteArrayInputStream; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.SimpleTimeZone; import java.util.TimeZone; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** * Unit tests for the */ public class AWS4SignerTest { public static final String PRIVATE_KEY_STRING = "-----BEGIN PRIVATE KEY-----\n" + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAILTGAZ/twm6FLNX/WDfMRtNGfiQ\n" + "3mUg4f8ACerU83pdJShkVxKSL1aKjAFZtagpOTbPbiHATyTAAUEjWhkIcLIP7+Xecx0zW3pu11yO\n" + "qjHU++oc8TL4+zTsPXrNU2+ohvw73g5aauVKgzW5qXO0r/wMsV/Y+T9BuBNvzcxt6xNNAgMBAAEC\n" + "gYACoxCj6OUenBKYvthLoJQT0c0JNppU/YGwqyaIBjzWJZR/KO6cYDf2DZre2BkSR6pwkWPN6Ftw\n" + "CTK9RmIliQcEeG6azpK0Rtv64ur5MIWRr1R+EPmDqVaIKm1m8C+tPbgMqZwYV0QPT4n2aD2Rgshd\n" + "MD3gw0MGvRDU46aHp2pHoQJBALs1BjkiNl8IA+aThZuDOqQvwAcePgu/IvQnv55js1Vv0h+HN/jI\n" + "nM8cLWl+RJzhOSmixTV6xuYPnzk35UUYCakCQQCy5gsFVoz+heX7mUgHWnlwU74NYOIoTc0uPJzW\n" + "cqgX7WzXZWGl9w1z/ENha8Pbj/pjVbmeTXDIQ+JjRTnrZ6sFAkEAq8mlk0ok0KG/Spg285TBfCbh\n" + "NOb4krjrr1bGTOc6in0ZOZtQrngRBTDbL0ISXk+CsAVQqJmo6TaOqufy+KttOQJASFlQS7BdBPIR\n" + "uFadEpw8UHkNe0ubKsGMIQ7SPsfPwx15zwJpIz1ua2GxvkxewQTRNisNDkAzREpv28W7TsB2IQJA\n" + "TJbwFpJd8KVG759unGT9kRFRfATQTwtbCM5Xi956Qiuknj0ErO2l/nOyTktdXZgp9KhWSAKKVUzp\n" + "7OSTTuwJ8A==\n" + "-----END PRIVATE KEY-----"; public static final String CERT_STRING = "-----BEGIN CERTIFICATE-----\n" + "MIICeDCCAeGgAwIBAgIGANyqR9onMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNVBAYT\n" + "AlVTMRMwEQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNBV1MxITAfBgNVBAMT\n" + "GEFXUyBMaW1pdGVkLUFzc3VyYW5jZSBDQTAeFw0wOTExMDMwMjQzMjlaFw0xMDEx\n" + "MDMwMjQzMjlaMFMxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpBbWF6b24uY29tMRcw\n" + "FQYDVQQLEw5BV1MtRGV2ZWxvcGVyczEWMBQGA1UEAxMNMWtwdXp2YzN0YXNmdDCB\n" + "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgtMYBn+3CboUs1f9YN8xG00Z+JDe\n" + "ZSDh/wAJ6tTzel0lKGRXEpIvVoqMAVm1qCk5Ns9uIcBPJMABQSNaGQhwsg/v5d5z\n" + "HTNbem7XXI6qMdT76hzxMvj7NOw9es1Tb6iG/DveDlpq5UqDNbmpc7Sv/AyxX9j5\n" + "P0G4E2/NzG3rE00CAwEAAaNXMFUwDgYDVR0PAQH/BAQDAgWgMBYGA1UdJQEB/wQM\n" + "MAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFLySbsuneGFATo5c\n" + "jKjkvEgs8cMOMA0GCSqGSIb3DQEBBQUAA4GBAHq2LLs3Av+HNjeD5Vd70vzMJGXx\n" + "tuWNvmrz98CznN+MvCB7meuygDSBuaVFA5Rkz3B5ucMsO2rT/ra5l5+XeVkdCyze\n" + "k+UrezIvY39xtrlrr5qxjuhXpgDmOPumdTb1vfGIb0mWTdnc86f92QFSmojgzY11\n" + "++q4zoqVhgiJOUh9\n" + "-----END CERTIFICATE-----"; private AWS4Signer signer = new AWS4Signer(); @Test public void testDoubleURLEncode() { // Sanity-check that doubleUrlEncode is true by default. assertTrue(signer.doubleUrlEncode); } @Test public void testSigning() throws Exception { final String EXPECTED_AUTHORIZATION_HEADER_WITHOUT_SHA256_HEADER = "AWS4-HMAC-SHA256 Credential=access/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date, Signature=77fe7c02927966018667f21d1dc3dfad9057e58401cbb9ed64f1b7868288e35a"; final String EXPECTED_AUTHORIZATION_HEADER_WITH_SHA256_HEADER = "AWS4-HMAC-SHA256 Credential=access/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date;x-amz-sha256, Signature=e73e20539446307a5dc71252dbd5b97e861f1d1267456abda3ebd8d57e519951"; AWSCredentials credentials = new BasicAWSCredentials("access", "secret"); // Test request without 'x-amz-sha256' header SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setOverrideDate(c.getTime()); signer.setServiceName("demo"); signer.sign(request, credentials); assertEquals(EXPECTED_AUTHORIZATION_HEADER_WITHOUT_SHA256_HEADER, request.getHeaders().get("Authorization")); // Test request with 'x-amz-sha256' header request = generateBasicRequest(); request.addHeader("x-amz-sha256", "required"); signer.sign(request, credentials); assertEquals(EXPECTED_AUTHORIZATION_HEADER_WITH_SHA256_HEADER, request.getHeaders().get("Authorization")); } @Test public void testPresigning() throws Exception { final String EXPECTED_AMZ_SIGNATURE = "bf7ae1c2f266d347e290a2aee7b126d38b8a695149d003b9fab2ed1eb6d6ebda"; final String EXPECTED_AMZ_CREDENTIALS = "access/19810216/us-east-1/demo/aws4_request"; final String EXPECTED_AMZ_HEADER = "19810216T063000Z"; final String EXPECTED_AMZ_EXPIRES = "604800"; AWSCredentials credentials = new BasicAWSCredentials("access", "secret"); // Test request without 'x-amz-sha256' header SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setOverrideDate(c.getTime()); signer.setServiceName("demo"); signer.presignRequest(request, credentials, null); assertEquals(EXPECTED_AMZ_SIGNATURE, request.getParameters().get("X-Amz-Signature").get(0)); assertEquals(EXPECTED_AMZ_CREDENTIALS, request.getParameters().get("X-Amz-Credential").get(0)); assertEquals(EXPECTED_AMZ_HEADER, request.getParameters().get("X-Amz-Date").get(0)); assertEquals(EXPECTED_AMZ_EXPIRES, request.getParameters().get("X-Amz-Expires").get(0)); } /** * Tests that if passed anonymous credentials, signer will not generate a signature */ @Test public void testAnonymous() throws Exception { AWSCredentials credentials = new AnonymousAWSCredentials(); SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setServiceName("demo"); signer.setOverrideDate(c.getTime()); signer.sign(request, credentials); assertNull(request.getHeaders().get("Authorization")); } /** * x-amzn-trace-id should not be signed as it may be mutated by proxies or load balancers. */ @Test public void xAmznTraceId_NotSigned() throws Exception { AWSCredentials credentials = new BasicAWSCredentials("akid", "skid"); SignableRequest<?> request = generateBasicRequest(); request.addHeader("X-Amzn-Trace-Id", " Root=1-584b150a-708479cb060007ffbf3ee1da;Parent=36d3dbcfd150aac9;Sampled=1"); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setServiceName("demo"); signer.setOverrideDate(c.getTime()); signer.sign(request, credentials); assertEquals( "AWS4-HMAC-SHA256 Credential=akid/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date, Signature=581d0042389009a28d461124138f1fe8eeb8daed87611d2a2b47fd3d68d81d73", request.getHeaders().get("Authorization")); } private SignableRequest<?> generateBasicRequest() { return MockRequestBuilder.create() .withContent(new ByteArrayInputStream("{\"TableName\": \"foo\"}".getBytes())) .withHeader("Host", "demo.us-east-1.amazonaws.com") .withHeader("x-amz-archive-description", "test test") .withPath("/") .withEndpoint("http://demo.us-east-1.amazonaws.com").build(); } private String getOldTimeStamp(Date date) { final SimpleDateFormat dateTimeFormat = new SimpleDateFormat( "yyyyMMdd'T'HHmmss'Z'"); dateTimeFormat.setTimeZone(new SimpleTimeZone(0, "UTC")); return dateTimeFormat.format(date); } @Test public void getTimeStamp() { Date now = new Date(); String timeStamp = AWS4SignerUtils.formatTimestamp(now.getTime()); String old = getOldTimeStamp(now); assertEquals(old, timeStamp); } private String getOldDateStamp(Date date) { final SimpleDateFormat dateStampFormat = new SimpleDateFormat("yyyyMMdd"); dateStampFormat.setTimeZone(new SimpleTimeZone(0, "UTC")); return dateStampFormat.format(date); } @Test public void getDateStamp() { Date now = new Date(); String dateStamp = AWS4SignerUtils.formatDateStamp(now.getTime()); String old = getOldDateStamp(now); assertEquals(old, dateStamp); } }