diff --git a/services/ec2/src/main/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptor.java b/services/ec2/src/main/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptor.java index 10605a907c91..a4ebd7265773 100644 --- a/services/ec2/src/main/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptor.java +++ b/services/ec2/src/main/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptor.java @@ -15,20 +15,20 @@ package software.amazon.awssdk.services.ec2.transform.internal; -import static software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute.AWS_CREDENTIALS; import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME; import java.net.URI; import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; -import software.amazon.awssdk.auth.credentials.AwsCredentials; -import software.amazon.awssdk.auth.credentials.CredentialUtils; -import software.amazon.awssdk.auth.signer.Aws4Signer; -import software.amazon.awssdk.auth.signer.params.Aws4PresignerParams; import software.amazon.awssdk.awscore.util.AwsHostNameUtils; import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.exception.SdkClientException; @@ -38,7 +38,14 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; +import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner; +import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner; +import software.amazon.awssdk.http.auth.aws.signer.SignerConstant; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; +import software.amazon.awssdk.http.auth.spi.signer.SignRequest; +import software.amazon.awssdk.http.auth.spi.signer.SignedRequest; +import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.protocols.query.AwsEc2ProtocolFactory; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ec2.Ec2Client; @@ -123,38 +130,54 @@ public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, Execu .method(SdkHttpMethod.GET) .build(); - Aws4Signer signer = Aws4Signer.create(); - Aws4PresignerParams signingParams = getPresignerParams(executionAttributes, sourceRegion, serviceName); - - SdkHttpFullRequest presignedRequest = signer.presign(requestForPresigning, signingParams); + URI presignedUrl = + sraPresignRequest(executionAttributes, requestForPresigning, sourceRegion); return request.toBuilder() .putRawQueryParameter("DestinationRegion", destinationRegion) - .putRawQueryParameter("PresignedUrl", presignedRequest.getUri().toString()) + .putRawQueryParameter("PresignedUrl", presignedUrl.toString()) .build(); } return request; } - private Aws4PresignerParams getPresignerParams(ExecutionAttributes attributes, String signingRegion, String signingName) { - return Aws4PresignerParams.builder() - .signingRegion(Region.of(signingRegion)) - .signingName(signingName) - .awsCredentials(resolveCredentials(attributes)) - .signingClockOverride(testClock) - .build(); + private URI sraPresignRequest(ExecutionAttributes executionAttributes, SdkHttpFullRequest request, + String signingRegion) { + SelectedAuthScheme selectedAuthScheme = executionAttributes.getAttribute(SELECTED_AUTH_SCHEME); + Instant signingInstant; + if (testClock != null) { + signingInstant = testClock.instant(); + } else { + signingInstant = Instant.now(); + } + + Clock signingClock = Clock.fixed(signingInstant, ZoneOffset.UTC); + Duration expirationDuration = SignerConstant.PRESIGN_URL_MAX_EXPIRATION_DURATION; + return doSraPresign(request, selectedAuthScheme, signingRegion, signingClock, expirationDuration); } - private AwsCredentials resolveCredentials(ExecutionAttributes attributes) { - return attributes.getOptionalAttribute(SELECTED_AUTH_SCHEME) - .map(selectedAuthScheme -> selectedAuthScheme.identity()) - .map(identityFuture -> CompletableFutureUtils.joinLikeSync(identityFuture)) - .filter(identity -> identity instanceof AwsCredentialsIdentity) - .map(identity -> { - AwsCredentialsIdentity awsCredentialsIdentity = (AwsCredentialsIdentity) identity; - return CredentialUtils.toCredentials(awsCredentialsIdentity); - }).orElse(attributes.getAttribute(AWS_CREDENTIALS)); + private URI doSraPresign(SdkHttpFullRequest request, + SelectedAuthScheme selectedAuthScheme, + String signingRegion, + Clock signingClock, + Duration expirationDuration) { + CompletableFuture identityFuture = selectedAuthScheme.identity(); + T identity = CompletableFutureUtils.joinLikeSync(identityFuture); + + SignRequest.Builder signRequestBuilder = SignRequest + .builder(identity) + .putProperty(AwsV4FamilyHttpSigner.AUTH_LOCATION, AwsV4FamilyHttpSigner.AuthLocation.QUERY_STRING) + .putProperty(AwsV4FamilyHttpSigner.EXPIRATION_DURATION, expirationDuration) + .putProperty(HttpSigner.SIGNING_CLOCK, signingClock) + .request(request) + .payload(request.contentStreamProvider().orElse(null)); + AuthSchemeOption authSchemeOption = selectedAuthScheme.authSchemeOption(); + authSchemeOption.forEachSignerProperty(signRequestBuilder::putProperty); + signRequestBuilder.putProperty(AwsV4HttpSigner.REGION_NAME, signingRegion); + HttpSigner signer = selectedAuthScheme.signer(); + SignedRequest signedRequest = signer.sign(signRequestBuilder.build()); + return signedRequest.request().getUri(); } /** diff --git a/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java b/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java index f2614e868191..f7e03816e6b9 100644 --- a/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java +++ b/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java @@ -18,6 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; import static software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute.AWS_CREDENTIALS; +import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.SERVICE_NAME; + import java.net.URI; import java.time.Clock; import java.time.Instant; @@ -28,6 +30,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.http.SdkHttpFullRequest; @@ -59,6 +62,7 @@ public void copySnapshotRequest_httpsProtocolAddedToEndpoint() { ExecutionAttributes attrs = new ExecutionAttributes(); attrs.putAttribute(AWS_CREDENTIALS, AwsBasicCredentials.create("foo", "bar")); + attrs.putAttribute(AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, "ec2"); SdkHttpRequest modifiedRequest = INTERCEPTOR.modifyHttpRequest(mockContext, attrs); @@ -82,8 +86,8 @@ public void copySnapshotRequest_generatesCorrectPresignedUrl() { "&X-Amz-Algorithm=AWS4-HMAC-SHA256" + "&X-Amz-Date=20200107T205609Z" + "&X-Amz-SignedHeaders=host" + - "&X-Amz-Expires=604800" + "&X-Amz-Credential=akid%2F20200107%2Fus-west-2%2Fec2%2Faws4_request" + + "&X-Amz-Expires=604800" + "&X-Amz-Signature=c1f5e34834292a86ff2b46b5e97cebaf2967b09641b4e2e60a382a37d137a03b"; ZoneId utcZone = ZoneId.of("UTC").normalized(); @@ -111,6 +115,7 @@ public void copySnapshotRequest_generatesCorrectPresignedUrl() { ExecutionAttributes attrs = new ExecutionAttributes(); attrs.putAttribute(AWS_CREDENTIALS, AwsBasicCredentials.create("akid", "skid")); + attrs.putAttribute(AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, "ec2"); SdkHttpRequest modifiedRequest = interceptor.modifyHttpRequest(mockContext, attrs);