Skip to content

Commit

Permalink
Update v4 request signer to log AWS4 canonical request if DEBUG level…
Browse files Browse the repository at this point in the history
… is enabled (#5153)
  • Loading branch information
zoewangg committed Apr 26, 2024
1 parent 29cc1aa commit e4fb225
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .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."
}
21 changes: 20 additions & 1 deletion core/http-auth-aws/pom.xml
Expand Up @@ -125,7 +125,26 @@
<artifactId>reactive-streams-tck</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>test-utils</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -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);
Expand Down
Expand Up @@ -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;
Expand All @@ -30,16 +35,14 @@

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))
.doubleUrlEncode(true)
.normalizePath(true)
.build();

DefaultV4RequestSigner requestSigner = new DefaultV4RequestSigner(v4Properties, "quux");

@Test
public void requestSigner_sign_shouldReturnSignedResult_butNotAddAnyAuthInfoToRequest() {
SdkHttpRequest.Builder request = SdkHttpRequest
Expand All @@ -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<LogEvent> 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");
}
}
}
38 changes: 38 additions & 0 deletions 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

0 comments on commit e4fb225

Please sign in to comment.