Skip to content

Commit

Permalink
Merge branch 'feature/master/sra-identity-auth' into sugmanue/sra-ia-…
Browse files Browse the repository at this point in the history
…merge-2.20.158-SNAPSHOT
  • Loading branch information
sugmanue authored Oct 3, 2023
2 parents 2c8dbed + 7017df5 commit 7307746
Show file tree
Hide file tree
Showing 17 changed files with 220 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.fromChecksumAlgorithm;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.AWS_CHUNKED;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.CONTENT_ENCODING;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_ECDSA_SIGNED_PAYLOAD;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_ECDSA_SIGNED_PAYLOAD_TRAILER;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_UNSIGNED_PAYLOAD_TRAILER;
Expand All @@ -40,6 +42,7 @@
import software.amazon.awssdk.http.auth.aws.internal.signer.chunkedencoding.TrailerProvider;
import software.amazon.awssdk.http.auth.aws.internal.signer.io.ChecksumInputStream;
import software.amazon.awssdk.http.auth.aws.internal.signer.io.ResettableContentStreamProvider;
import software.amazon.awssdk.utils.BinaryUtils;
import software.amazon.awssdk.utils.Pair;
import software.amazon.awssdk.utils.StringInputStream;
import software.amazon.awssdk.utils.Validate;
Expand Down Expand Up @@ -144,6 +147,7 @@ public void beforeSigning(SdkHttpRequest.Builder request, ContentStreamProvider
request.appendHeader(X_AMZ_TRAILER, checksumHeaderName);
}
request.putHeader(Header.CONTENT_LENGTH, Long.toString(encodedContentLength));
request.appendHeader(CONTENT_ENCODING, AWS_CHUNKED);
}

/**
Expand Down Expand Up @@ -220,8 +224,8 @@ private long calculateChecksumTrailerLength(String checksumHeaderName) {

// get the base checksum for the algorithm
SdkChecksum sdkChecksum = fromChecksumAlgorithm(checksumAlgorithm);
// size of checksum value as hex-string
lengthInBytes += sdkChecksum.getChecksum().length();
// size of checksum value as encoded-string
lengthInBytes += BinaryUtils.toBase64(sdkChecksum.getChecksumBytes()).length();

// terminating \r\n
return lengthInBytes + 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.fromChecksumAlgorithm;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.AWS_CHUNKED;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.CONTENT_ENCODING;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_SIGNED_PAYLOAD;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_SIGNED_PAYLOAD_TRAILER;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.STREAMING_UNSIGNED_PAYLOAD_TRAILER;
Expand All @@ -43,6 +45,7 @@
import software.amazon.awssdk.http.auth.aws.internal.signer.chunkedencoding.TrailerProvider;
import software.amazon.awssdk.http.auth.aws.internal.signer.io.ChecksumInputStream;
import software.amazon.awssdk.http.auth.aws.internal.signer.io.ResettableContentStreamProvider;
import software.amazon.awssdk.utils.BinaryUtils;
import software.amazon.awssdk.utils.Pair;
import software.amazon.awssdk.utils.StringInputStream;
import software.amazon.awssdk.utils.Validate;
Expand Down Expand Up @@ -161,6 +164,7 @@ public void beforeSigning(SdkHttpRequest.Builder request, ContentStreamProvider
request.appendHeader(X_AMZ_TRAILER, checksumHeaderName);
}
request.putHeader(Header.CONTENT_LENGTH, Long.toString(encodedContentLength));
request.appendHeader(CONTENT_ENCODING, AWS_CHUNKED);
}

/**
Expand Down Expand Up @@ -237,8 +241,8 @@ private long calculateChecksumTrailerLength(String checksumHeaderName) {

// get the base checksum for the algorithm
SdkChecksum sdkChecksum = fromChecksumAlgorithm(checksumAlgorithm);
// size of checksum value as hex-string
lengthInBytes += sdkChecksum.getChecksum().length();
// size of checksum value as encoded-string
lengthInBytes += BinaryUtils.toBase64(sdkChecksum.getChecksumBytes()).length();

// terminating \r\n
return lengthInBytes + 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@
package software.amazon.awssdk.http.auth.aws.internal.signer;

import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA256;
import static software.amazon.awssdk.http.auth.aws.internal.signer.FlexibleChecksummer.option;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.ConstantChecksumAlgorithm;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.X_AMZ_CONTENT_SHA256;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Map;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import org.reactivestreams.Publisher;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm;
import software.amazon.awssdk.http.ContentStreamProvider;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.utils.ImmutableMap;
import software.amazon.awssdk.utils.BinaryUtils;

/**
* An interface for defining how a checksum is formed from a payload synchronously and asynchronously.
Expand All @@ -43,7 +43,9 @@ public interface Checksummer {
* x-amz-content-sha256 header.
*/
static Checksummer create() {
return new FlexibleChecksummer(Collections.singletonMap(X_AMZ_CONTENT_SHA256, SHA256));
return new FlexibleChecksummer(
option().headerName(X_AMZ_CONTENT_SHA256).algorithm(SHA256).formatter(BinaryUtils::toHex).build()
);
}

/**
Expand All @@ -52,12 +54,12 @@ static Checksummer create() {
*/
static Checksummer forFlexibleChecksum(ChecksumAlgorithm checksumAlgorithm) {
if (checksumAlgorithm != null) {
Map<String, ChecksumAlgorithm> checksums = ImmutableMap.of(
X_AMZ_CONTENT_SHA256, SHA256,
checksumHeaderName(checksumAlgorithm), checksumAlgorithm
return new FlexibleChecksummer(
option().headerName(X_AMZ_CONTENT_SHA256).algorithm(SHA256).formatter(BinaryUtils::toHex)
.build(),
option().headerName(checksumHeaderName(checksumAlgorithm)).algorithm(checksumAlgorithm)
.formatter(BinaryUtils::toBase64).build()
);

return new FlexibleChecksummer(checksums);
}

throw new IllegalArgumentException("Checksum Algorithm cannot be null!");
Expand All @@ -77,17 +79,21 @@ static Checksummer forPrecomputed256Checksum(String precomputedSha256) {
*/
static Checksummer forFlexibleChecksum(String precomputedSha256, ChecksumAlgorithm checksumAlgorithm) {
if (checksumAlgorithm != null) {
Map<String, ChecksumAlgorithm> checksums = ImmutableMap.of(
X_AMZ_CONTENT_SHA256, new ConstantChecksumAlgorithm(precomputedSha256),
checksumHeaderName(checksumAlgorithm), checksumAlgorithm
return new FlexibleChecksummer(
option().headerName(X_AMZ_CONTENT_SHA256).algorithm(new ConstantChecksumAlgorithm(precomputedSha256))
.formatter(b -> new String(b, StandardCharsets.UTF_8)).build(),
option().headerName(checksumHeaderName(checksumAlgorithm)).algorithm(checksumAlgorithm)
.formatter(BinaryUtils::toBase64).build()
);

return new FlexibleChecksummer(checksums);
}

throw new IllegalArgumentException("Checksum Algorithm cannot be null!");
}

static Checksummer forNoOp() {
return new FlexibleChecksummer();
}

/**
* Given a payload, calculate a checksum and add it to the request.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package software.amazon.awssdk.http.auth.aws.internal.signer;

import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.CredentialUtils.sanitizeCredentials;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.OptionalDependencyLoaderUtil.getEventStreamV4PayloadSigner;
import static software.amazon.awssdk.http.auth.aws.internal.signer.util.SignerConstant.PRESIGN_URL_MAX_EXPIRATION_DURATION;
Expand All @@ -31,6 +32,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm;
import software.amazon.awssdk.http.ContentStreamProvider;
import software.amazon.awssdk.http.Header;
import software.amazon.awssdk.http.SdkHttpRequest;
Expand Down Expand Up @@ -77,6 +79,11 @@ private static V4RequestSigner v4RequestSigner(

AuthLocation authLocation = request.requireProperty(AUTH_LOCATION, AuthLocation.HEADER);
Duration expirationDuration = request.property(EXPIRATION_DURATION);
boolean isAnonymous = CredentialUtils.isAnonymous(request.identity());

if (isAnonymous) {
return V4RequestSigner.anonymous(v4Properties);
}

Function<V4Properties, V4RequestSigner> requestSigner;
switch (authLocation) {
Expand All @@ -99,12 +106,25 @@ private static V4RequestSigner v4RequestSigner(
return requestSigner.apply(v4Properties);
}

private static boolean hasChecksumHeader(BaseSignRequest<?, ? extends AwsCredentialsIdentity> request) {
ChecksumAlgorithm checksumAlgorithm = request.property(CHECKSUM_ALGORITHM);

if (checksumAlgorithm != null) {
String checksumHeaderName = checksumHeaderName(checksumAlgorithm);
return request.request().firstMatchingHeader(checksumHeaderName).isPresent();
}

return false;
}

private static Checksummer checksummer(BaseSignRequest<?, ? extends AwsCredentialsIdentity> request) {
boolean isPayloadSigning = isPayloadSigning(request);
boolean isEventStreaming = isEventStreaming(request.request());
boolean isChunkEncoding = request.requireProperty(CHUNK_ENCODING_ENABLED, false);
boolean hasChecksumHeader = hasChecksumHeader(request);
boolean isChunkEncoding = request.requireProperty(CHUNK_ENCODING_ENABLED, false) && !hasChecksumHeader;
boolean isTrailing = request.request().firstMatchingHeader(X_AMZ_TRAILER).isPresent();
boolean isFlexible = request.hasProperty(CHECKSUM_ALGORITHM);
boolean isAnonymous = CredentialUtils.isAnonymous(request.identity());

if (isEventStreaming) {
return Checksummer.forPrecomputed256Checksum(STREAMING_EVENTS_PAYLOAD);
Expand All @@ -118,23 +138,26 @@ private static Checksummer checksummer(BaseSignRequest<?, ? extends AwsCredentia
return Checksummer.forPrecomputed256Checksum(STREAMING_SIGNED_PAYLOAD);
}

if (request.hasProperty(CHECKSUM_ALGORITHM)) {
if (isFlexible) {
return Checksummer.forFlexibleChecksum(request.property(CHECKSUM_ALGORITHM));
}
return Checksummer.create();
}

if (isChunkEncoding) {
if (isFlexible || isTrailing) {
if (isFlexible || isTrailing) {
if (isChunkEncoding) {
return Checksummer.forPrecomputed256Checksum(STREAMING_UNSIGNED_PAYLOAD_TRAILER);
}
throw new UnsupportedOperationException("Chunk-Encoding without Payload-Signing must have a trailer!");
}

if (isFlexible) {
if (isFlexible && !hasChecksumHeader) {
return Checksummer.forFlexibleChecksum(UNSIGNED_PAYLOAD, request.property(CHECKSUM_ALGORITHM));
}

if (isAnonymous) {
return Checksummer.forNoOp();
}

return Checksummer.forPrecomputed256Checksum(UNSIGNED_PAYLOAD);
}

Expand All @@ -144,7 +167,9 @@ private static V4PayloadSigner v4PayloadSigner(

boolean isPayloadSigning = isPayloadSigning(request);
boolean isEventStreaming = isEventStreaming(request.request());
boolean isChunkEncoding = request.requireProperty(CHUNK_ENCODING_ENABLED, false);
boolean isChunkEncoding = request.requireProperty(CHUNK_ENCODING_ENABLED, false) && !hasChecksumHeader(request);
boolean isTrailing = request.request().firstMatchingHeader(X_AMZ_TRAILER).isPresent();
boolean isFlexible = request.hasProperty(CHECKSUM_ALGORITHM);

if (isEventStreaming) {
if (isPayloadSigning) {
Expand All @@ -157,7 +182,7 @@ private static V4PayloadSigner v4PayloadSigner(
throw new UnsupportedOperationException("Unsigned payload is not supported with event-streaming.");
}

if (isChunkEncoding) {
if ((isChunkEncoding && isPayloadSigning) || (isChunkEncoding && (isTrailing || isFlexible))) {
return AwsChunkedV4PayloadSigner.builder()
.credentialScope(properties.getCredentialScope())
.chunkSize(DEFAULT_CHUNK_SIZE_IN_BYTES)
Expand Down Expand Up @@ -199,12 +224,6 @@ private static SignedRequest doSign(SignRequest<? extends AwsCredentialsIdentity
Checksummer checksummer,
V4RequestSigner requestSigner,
V4PayloadSigner payloadSigner) {
if (CredentialUtils.isAnonymous(request.identity())) {
return SignedRequest.builder()
.request(request.request())
.payload(request.payload().orElse(null))
.build();
}

SdkHttpRequest.Builder requestBuilder = request.request().toBuilder();

Expand All @@ -214,7 +233,7 @@ private static SignedRequest doSign(SignRequest<? extends AwsCredentialsIdentity

V4Context v4Context = requestSigner.sign(requestBuilder);

ContentStreamProvider payload = payloadSigner.sign(request.payload().orElse(null), v4Context);
ContentStreamProvider payload = request.payload().map(p -> payloadSigner.sign(p, v4Context)).orElse(null);

return SignedRequest.builder()
.request(v4Context.getSignedRequest().build())
Expand All @@ -226,14 +245,6 @@ private static CompletableFuture<AsyncSignedRequest> doSign(AsyncSignRequest<? e
Checksummer checksummer,
V4RequestSigner requestSigner,
V4PayloadSigner payloadSigner) {
if (CredentialUtils.isAnonymous(request.identity())) {
return CompletableFuture.completedFuture(
AsyncSignedRequest.builder()
.request(request.request())
.payload(request.payload().orElse(null))
.build()
);
}

SdkHttpRequest.Builder requestBuilder = request.request().toBuilder();

Expand Down Expand Up @@ -261,7 +272,11 @@ private static Duration validateExpirationDuration(Duration expirationDuration)
}

private static boolean isPayloadSigning(BaseSignRequest<?, ? extends AwsCredentialsIdentity> request) {
return request.requireProperty(PAYLOAD_SIGNING_ENABLED, true) || !"https".equals(request.request().protocol());
boolean isAnonymous = CredentialUtils.isAnonymous(request.identity());
boolean isPayloadSigningEnabled = request.requireProperty(PAYLOAD_SIGNING_ENABLED, true);
boolean isEncrypted = "https".equals(request.request().protocol());

return !isAnonymous && (isPayloadSigningEnabled || !isEncrypted);
}

private static boolean isEventStreaming(SdkHttpRequest request) {
Expand Down
Loading

0 comments on commit 7307746

Please sign in to comment.