Skip to content

Commit 27ffdf3

Browse files
authored
Fix Sigv4a-signed requests to endpoints with non-standard ports. (#2725)
1 parent 213c54c commit 27ffdf3

File tree

3 files changed

+53
-9
lines changed

3 files changed

+53
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"contributor": "",
4+
"type": "bugfix",
5+
"description": "Update Sigv4a signer to include the port in the Host header, when the port does not match the standard port for the protocol. This allows requests to endpoints with non-standard ports to succeed."
6+
}

core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/SigningUtils.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
package software.amazon.awssdk.authcrt.signer.internal;
1717

18-
import static software.amazon.awssdk.utils.CollectionUtils.isNullOrEmpty;
19-
2018
import java.nio.charset.StandardCharsets;
2119
import java.time.Clock;
2220
import java.time.Duration;
@@ -35,6 +33,7 @@
3533
import software.amazon.awssdk.crt.auth.credentials.Credentials;
3634
import software.amazon.awssdk.http.SdkHttpFullRequest;
3735
import software.amazon.awssdk.utils.StringUtils;
36+
import software.amazon.awssdk.utils.http.SdkHttpUtils;
3837

3938
@SdkInternalApi
4039
public class SigningUtils {
@@ -116,19 +115,19 @@ public static SdkHttpFullRequest sanitizeSdkRequestForCrtSigning(SdkHttpFullRequ
116115

117116
builder.clearHeaders();
118117

119-
// Add host if missing
120-
Map<String, List<String>> headers = request.headers();
121-
if (isNullOrEmpty(headers.get(HOST_HEADER))) {
122-
builder.putHeader(HOST_HEADER, request.host());
123-
}
124-
125118
// Filter headers that will cause signing to fail
126-
for (Map.Entry<String, List<String>> header: headers.entrySet()) {
119+
for (Map.Entry<String, List<String>> header: request.headers().entrySet()) {
127120
if (!FORBIDDEN_HEADERS.contains(header.getKey())) {
128121
builder.putHeader(header.getKey(), header.getValue());
129122
}
130123
}
131124

125+
// Add host, which must be signed. We ignore any pre-existing Host header to match the behavior of the SigV4 signer.
126+
String hostHeader = SdkHttpUtils.isUsingStandardPort(request.protocol(), request.port())
127+
? request.host()
128+
: request.host() + ":" + request.port();
129+
builder.putHeader(HOST_HEADER, hostHeader);
130+
132131
builder.clearQueryParameters();
133132

134133
// Filter query parameters that will cause signing to fail

core/auth-crt/src/test/java/software/amazon/awssdk/authcrt/signer/AwsCrtV4aSignerTest.java

+39
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,45 @@ public void setup() {
4444
v4aSigner = AwsCrtV4aSigner.create();
4545
}
4646

47+
@Test
48+
public void hostHeaderExcludesStandardHttpPort() {
49+
SigningTestCase testCase = SignerTestUtils.createBasicHeaderSigningTestCase();
50+
ExecutionAttributes executionAttributes = SignerTestUtils.buildBasicExecutionAttributes(testCase);
51+
52+
SdkHttpFullRequest request = testCase.requestBuilder.protocol("http")
53+
.port(80)
54+
.build();
55+
SdkHttpFullRequest signed = v4aSigner.sign(request, executionAttributes);
56+
57+
assertThat(signed.firstMatchingHeader("Host")).hasValue("demo.us-east-1.amazonaws.com");
58+
}
59+
60+
@Test
61+
public void hostHeaderExcludesStandardHttpsPort() {
62+
SigningTestCase testCase = SignerTestUtils.createBasicHeaderSigningTestCase();
63+
ExecutionAttributes executionAttributes = SignerTestUtils.buildBasicExecutionAttributes(testCase);
64+
65+
SdkHttpFullRequest request = testCase.requestBuilder.protocol("https")
66+
.port(443)
67+
.build();
68+
SdkHttpFullRequest signed = v4aSigner.sign(request, executionAttributes);
69+
70+
assertThat(signed.firstMatchingHeader("Host")).hasValue("demo.us-east-1.amazonaws.com");
71+
}
72+
73+
@Test
74+
public void hostHeaderIncludesNonStandardPorts() {
75+
SigningTestCase testCase = SignerTestUtils.createBasicHeaderSigningTestCase();
76+
ExecutionAttributes executionAttributes = SignerTestUtils.buildBasicExecutionAttributes(testCase);
77+
78+
SdkHttpFullRequest request = testCase.requestBuilder.protocol("http")
79+
.port(443)
80+
.build();
81+
SdkHttpFullRequest signed = v4aSigner.sign(request, executionAttributes);
82+
83+
assertThat(signed.firstMatchingHeader("Host")).hasValue("demo.us-east-1.amazonaws.com:443");
84+
}
85+
4786
@Test
4887
public void testHeaderSigning() {
4988
SigningTestCase testCase = SignerTestUtils.createBasicHeaderSigningTestCase();

0 commit comments

Comments
 (0)