From e4fb225dc46c86eff09b40b038ba21c02add6130 Mon Sep 17 00:00:00 2001
From: Zoe Wang <33073555+zoewangg@users.noreply.github.com>
Date: Fri, 26 Apr 2024 14:48:22 -0700
Subject: [PATCH] Update v4 request signer to log AWS4 canonical request if
DEBUG level is enabled (#5153)
---
.../bugfix-AWSSDKforJavav2-66877e6.json | 6 +++
core/http-auth-aws/pom.xml | 21 +++++++++-
.../signer/DefaultV4RequestSigner.java | 5 ++-
.../signer/DefaultRequestSignerTest.java | 32 ++++++++++------
.../src/test/resources/log4j2.properties | 38 +++++++++++++++++++
5 files changed, 89 insertions(+), 13 deletions(-)
create mode 100644 .changes/next-release/bugfix-AWSSDKforJavav2-66877e6.json
create mode 100644 core/http-auth-aws/src/test/resources/log4j2.properties
diff --git a/.changes/next-release/bugfix-AWSSDKforJavav2-66877e6.json b/.changes/next-release/bugfix-AWSSDKforJavav2-66877e6.json
new file mode 100644
index 000000000000..4a45e056e13c
--- /dev/null
+++ b/.changes/next-release/bugfix-AWSSDKforJavav2-66877e6.json
@@ -0,0 +1,6 @@
+{
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Log `AWS4 Canonical Request` in signer if DEBUG level is enabled."
+}
diff --git a/core/http-auth-aws/pom.xml b/core/http-auth-aws/pom.xml
index 9ed593d1297d..1656df0234c7 100644
--- a/core/http-auth-aws/pom.xml
+++ b/core/http-auth-aws/pom.xml
@@ -125,7 +125,26 @@
reactive-streams-tck
test
-
+
+ software.amazon.awssdk
+ test-utils
+ test
+
+
+ org.apache.logging.log4j
+ log4j-api
+ test
+
+
+ org.apache.logging.log4j
+ log4j-core
+ test
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ test
+
diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultV4RequestSigner.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultV4RequestSigner.java
index 1935fa10107a..21565d43551e 100644
--- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultV4RequestSigner.java
+++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultV4RequestSigner.java
@@ -52,8 +52,11 @@ public V4RequestSigningResult sign(SdkHttpRequest.Builder requestBuilder) {
// Step 1: Create a canonical request
V4CanonicalRequest canonicalRequest = createCanonicalRequest(requestBuilder.build(), contentHash);
+ String canonicalRequestString = canonicalRequest.getCanonicalRequestString();
+ LOG.debug(() -> "AWS4 Canonical Request: " + canonicalRequestString);
+
// Step 2: Create a hash of the canonical request
- String canonicalRequestHash = hashCanonicalRequest(canonicalRequest.getCanonicalRequestString());
+ String canonicalRequestHash = hashCanonicalRequest(canonicalRequestString);
// Step 2: Create a hash of the canonical request
String stringToSign = createSignString(canonicalRequestHash);
diff --git a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultRequestSignerTest.java b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultRequestSignerTest.java
index dfff39536aba..b212e283ec3b 100644
--- a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultRequestSignerTest.java
+++ b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/DefaultRequestSignerTest.java
@@ -20,6 +20,11 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static software.amazon.awssdk.utils.BinaryUtils.toHex;
+import java.util.List;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LogEvent;
+import software.amazon.awssdk.testutils.LogCaptor;
+
import java.net.URI;
import java.time.Clock;
import java.time.Instant;
@@ -30,7 +35,7 @@
public class DefaultRequestSignerTest {
- V4Properties v4Properties = V4Properties.builder()
+ private V4Properties v4Properties = V4Properties.builder()
.credentials(AwsCredentialsIdentity.create("foo", "bar"))
.credentialScope(new CredentialScope("baz", "qux", Instant.EPOCH))
.signingClock(Clock.fixed(Instant.EPOCH, UTC))
@@ -38,8 +43,6 @@ public class DefaultRequestSignerTest {
.normalizePath(true)
.build();
- DefaultV4RequestSigner requestSigner = new DefaultV4RequestSigner(v4Properties, "quux");
-
@Test
public void requestSigner_sign_shouldReturnSignedResult_butNotAddAnyAuthInfoToRequest() {
SdkHttpRequest.Builder request = SdkHttpRequest
@@ -55,13 +58,20 @@ public void requestSigner_sign_shouldReturnSignedResult_butNotAddAnyAuthInfoToRe
+ "host\nquux";
String expectedHost = "localhost";
- V4RequestSigningResult requestSigningResult = requestSigner.sign(request);
-
- assertEquals(expectedContentHash, requestSigningResult.getContentHash());
- assertEquals(expectedSigningKeyHex, toHex(requestSigningResult.getSigningKey()));
- assertEquals(expectedSignature, requestSigningResult.getSignature());
- assertEquals(expectedCanonicalRequestString, requestSigningResult.getCanonicalRequest().getCanonicalRequestString());
- assertEquals(expectedHost, requestSigningResult.getSignedRequest().firstMatchingHeader("Host").orElse(""));
- assertThat(requestSigningResult.getSignedRequest().build()).usingRecursiveComparison().isEqualTo(request.build());
+ try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) {
+ DefaultV4RequestSigner requestSigner = new DefaultV4RequestSigner(v4Properties, "quux");
+ V4RequestSigningResult requestSigningResult = requestSigner.sign(request);
+ assertEquals(expectedContentHash, requestSigningResult.getContentHash());
+ assertEquals(expectedSigningKeyHex, toHex(requestSigningResult.getSigningKey()));
+ assertEquals(expectedSignature, requestSigningResult.getSignature());
+ assertEquals(expectedCanonicalRequestString, requestSigningResult.getCanonicalRequest().getCanonicalRequestString());
+ assertEquals(expectedHost, requestSigningResult.getSignedRequest().firstMatchingHeader("Host").orElse(""));
+ assertThat(requestSigningResult.getSignedRequest().build()).usingRecursiveComparison().isEqualTo(request.build());
+ List logEvents = logCaptor.loggedEvents();
+ assertThat(logEvents).hasSize(3);
+ assertThat(logEvents.get(0).getMessage().getFormattedMessage()).contains("AWS4 Canonical Request");
+ assertThat(logEvents.get(1).getMessage().getFormattedMessage()).contains("AWS4 Canonical Request Hash");
+ assertThat(logEvents.get(2).getMessage().getFormattedMessage()).contains("AWS4 String to sign");
+ }
}
}
diff --git a/core/http-auth-aws/src/test/resources/log4j2.properties b/core/http-auth-aws/src/test/resources/log4j2.properties
new file mode 100644
index 000000000000..5cc1706db5bd
--- /dev/null
+++ b/core/http-auth-aws/src/test/resources/log4j2.properties
@@ -0,0 +1,38 @@
+#
+# Copyright 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.
+#
+
+status = warn
+
+appender.console.type = Console
+appender.console.name = ConsoleAppender
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n%throwable
+
+rootLogger.level = error
+rootLogger.appenderRef.stdout.ref = ConsoleAppender
+
+# Uncomment below to enable more specific logging
+#
+#logger.sdk.name = software.amazon.awssdk
+#logger.sdk.level = debug
+#
+#logger.request.name = software.amazon.awssdk.request
+#logger.request.level = debug
+#
+#logger.apache.name = org.apache.http.wire
+#logger.apache.level = debug
+#
+#logger.netty.name = io.netty.handler.logging
+#logger.netty.level = debug