diff --git a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3BasicCredentialsRestIT.java b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3BasicCredentialsRestIT.java index 10901424512a3..cd17138a16fea 100644 --- a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3BasicCredentialsRestIT.java +++ b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3BasicCredentialsRestIT.java @@ -33,7 +33,7 @@ public class RepositoryS3BasicCredentialsRestIT extends AbstractRepositoryS3Rest private static final String SECRET_KEY = PREFIX + "secret-key"; private static final String CLIENT = "basic_credentials_client"; - private static final S3HttpFixture s3Fixture = new S3HttpFixture(true, BUCKET, BASE_PATH, fixedAccessKey(ACCESS_KEY)); + private static final S3HttpFixture s3Fixture = new S3HttpFixture(true, BUCKET, BASE_PATH, fixedAccessKey(ACCESS_KEY, "*", "s3")); public static ElasticsearchCluster cluster = ElasticsearchCluster.local() .module("repository-s3") diff --git a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java index 065d1c6c9ea27..0d133b30b5e39 100644 --- a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java +++ b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java @@ -39,7 +39,12 @@ public class RepositoryS3RestReloadCredentialsIT extends ESRestTestCase { private static volatile String repositoryAccessKey; - public static final S3HttpFixture s3Fixture = new S3HttpFixture(true, BUCKET, BASE_PATH, mutableAccessKey(() -> repositoryAccessKey)); + public static final S3HttpFixture s3Fixture = new S3HttpFixture( + true, + BUCKET, + BASE_PATH, + mutableAccessKey(() -> repositoryAccessKey, "*", "s3") + ); private static final MutableSettingsProvider keystoreSettings = new MutableSettingsProvider(); diff --git a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3SessionCredentialsRestIT.java b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3SessionCredentialsRestIT.java index a8009d594926f..c0b5aa989281c 100644 --- a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3SessionCredentialsRestIT.java +++ b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3SessionCredentialsRestIT.java @@ -38,7 +38,7 @@ public class RepositoryS3SessionCredentialsRestIT extends AbstractRepositoryS3Re true, BUCKET, BASE_PATH, - fixedAccessKeyAndToken(ACCESS_KEY, SESSION_TOKEN) + fixedAccessKeyAndToken(ACCESS_KEY, SESSION_TOKEN, "*", "s3") ); public static ElasticsearchCluster cluster = ElasticsearchCluster.local() diff --git a/modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3BlobContainer.java b/modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3BlobContainer.java index d7f5a6e6dfe36..6963e329ddc86 100644 --- a/modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3BlobContainer.java +++ b/modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3BlobContainer.java @@ -469,7 +469,7 @@ void executeSingleUpload( S3BlobStore.configureRequestForMetrics(putRequest, blobStore, Operation.PUT_OBJECT, purpose); try (AmazonS3Reference clientReference = s3BlobStore.clientReference()) { - SocketAccess.doPrivilegedVoid(() -> { clientReference.client().putObject(putRequest); }); + SocketAccess.doPrivilegedVoid(() -> clientReference.client().putObject(putRequest)); } catch (final AmazonClientException e) { throw new IOException("Unable to upload object [" + blobName + "] using a single upload", e); } diff --git a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java index 89919f0f3ddf1..c0b7b447f8860 100644 --- a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java +++ b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java @@ -36,7 +36,7 @@ public class RepositoryS3ClientYamlTestSuiteIT extends AbstractRepositoryS3Clien true, "bucket", "base_path_integration_tests", - fixedAccessKey(ACCESS_KEY) + fixedAccessKey(ACCESS_KEY, "*", "s3") ); public static ElasticsearchCluster cluster = ElasticsearchCluster.local() diff --git a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2EnvironmentVariableCredentialsIT.java b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2EnvironmentVariableCredentialsIT.java index 7fc5a2b4bcfae..620aa3d9b7282 100644 --- a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2EnvironmentVariableCredentialsIT.java +++ b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2EnvironmentVariableCredentialsIT.java @@ -29,7 +29,7 @@ public class DiscoveryEc2EnvironmentVariableCredentialsIT extends DiscoveryEc2Cl private static final String ACCESS_KEY = PREFIX + "-access-key"; private static final AwsEc2HttpFixture ec2ApiFixture = new AwsEc2HttpFixture( - fixedAccessKey(ACCESS_KEY), + fixedAccessKey(ACCESS_KEY, REGION, "ec2"), DiscoveryEc2EnvironmentVariableCredentialsIT::getAvailableTransportEndpoints ); diff --git a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreCredentialsIT.java b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreCredentialsIT.java index c198ae5903ad4..8721b944d87de 100644 --- a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreCredentialsIT.java +++ b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreCredentialsIT.java @@ -29,7 +29,7 @@ public class DiscoveryEc2KeystoreCredentialsIT extends DiscoveryEc2ClusterFormat private static final String ACCESS_KEY = PREFIX + "-access-key"; private static final AwsEc2HttpFixture ec2ApiFixture = new AwsEc2HttpFixture( - fixedAccessKey(ACCESS_KEY), + fixedAccessKey(ACCESS_KEY, REGION, "ec2"), DiscoveryEc2KeystoreCredentialsIT::getAvailableTransportEndpoints ); diff --git a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreSessionCredentialsIT.java b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreSessionCredentialsIT.java index e26ca0889e7b5..5e38f80d22611 100644 --- a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreSessionCredentialsIT.java +++ b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2KeystoreSessionCredentialsIT.java @@ -30,7 +30,7 @@ public class DiscoveryEc2KeystoreSessionCredentialsIT extends DiscoveryEc2Cluste private static final String SESSION_TOKEN = PREFIX + "-session-token"; private static final AwsEc2HttpFixture ec2ApiFixture = new AwsEc2HttpFixture( - fixedAccessKeyAndToken(ACCESS_KEY, SESSION_TOKEN), + fixedAccessKeyAndToken(ACCESS_KEY, SESSION_TOKEN, REGION, "ec2"), DiscoveryEc2KeystoreSessionCredentialsIT::getAvailableTransportEndpoints ); diff --git a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2SystemPropertyCredentialsIT.java b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2SystemPropertyCredentialsIT.java index 28ca11696569b..745cd0a76b4ff 100644 --- a/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2SystemPropertyCredentialsIT.java +++ b/plugins/discovery-ec2/src/javaRestTest/java/org/elasticsearch/discovery/ec2/DiscoveryEc2SystemPropertyCredentialsIT.java @@ -29,7 +29,7 @@ public class DiscoveryEc2SystemPropertyCredentialsIT extends DiscoveryEc2Cluster private static final String ACCESS_KEY = PREFIX + "-access-key"; private static final AwsEc2HttpFixture ec2ApiFixture = new AwsEc2HttpFixture( - fixedAccessKey(ACCESS_KEY), + fixedAccessKey(ACCESS_KEY, REGION, "ec2"), DiscoveryEc2SystemPropertyCredentialsIT::getAvailableTransportEndpoints ); diff --git a/test/fixtures/aws-fixture-utils/src/main/java/fixture/aws/AwsCredentialsUtils.java b/test/fixtures/aws-fixture-utils/src/main/java/fixture/aws/AwsCredentialsUtils.java index 9000e06ca1350..aab6504f2d8c3 100644 --- a/test/fixtures/aws-fixture-utils/src/main/java/fixture/aws/AwsCredentialsUtils.java +++ b/test/fixtures/aws-fixture-utils/src/main/java/fixture/aws/AwsCredentialsUtils.java @@ -24,26 +24,55 @@ public enum AwsCredentialsUtils { ; /** - * @return an authorization predicate that ensures the access key matches the given values. + * @return an authorization predicate that ensures the authorization header matches the given access key, region and service name. + * @see AWS v4 Signatures + * @param region the name of the AWS region used to sign the request, or {@code *} to skip validation of the region parameter */ - public static BiPredicate fixedAccessKey(String accessKey) { - return mutableAccessKey(() -> accessKey); + public static BiPredicate fixedAccessKey(String accessKey, String region, String serviceName) { + return mutableAccessKey(() -> accessKey, region, serviceName); } /** - * @return an authorization predicate that ensures the access key matches one supplied by the given supplier. + * @return an authorization predicate that ensures the authorization header matches the access key supplied by the given supplier, + * and also matches the given region and service name. + * @see AWS v4 Signatures + * @param region the name of the AWS region used to sign the request, or {@code *} to skip validation of the region parameter */ - public static BiPredicate mutableAccessKey(Supplier accessKeySupplier) { - return (authorizationHeader, sessionTokenHeader) -> authorizationHeader != null - && authorizationHeader.contains(accessKeySupplier.get()); + public static BiPredicate mutableAccessKey(Supplier accessKeySupplier, String region, String serviceName) { + return (authorizationHeader, sessionTokenHeader) -> { + if (authorizationHeader == null) { + return false; + } + + final var accessKey = accessKeySupplier.get(); + final var expectedPrefix = "AWS4-HMAC-SHA256 Credential=" + accessKey + "/"; + if (authorizationHeader.startsWith(expectedPrefix) == false) { + return false; + } + + if (region.equals("*")) { + // skip region validation; TODO eliminate this when region is fixed in all tests + return authorizationHeader.contains("/" + serviceName + "/aws4_request, "); + } + + final var remainder = authorizationHeader.substring(expectedPrefix.length() + "YYYYMMDD".length() /* skip over date field */); + return remainder.startsWith("/" + region + "/" + serviceName + "/aws4_request, "); + }; } /** - * @return an authorization predicate that ensures the access key and session token both match the given values. + * @return an authorization predicate that ensures the access key, session token, region and service name all match the given values. + * @see AWS v4 Signatures + * @param region the name of the AWS region used to sign the request, or {@code *} to skip validation of the region parameter */ - public static BiPredicate fixedAccessKeyAndToken(String accessKey, String sessionToken) { + public static BiPredicate fixedAccessKeyAndToken( + String accessKey, + String sessionToken, + String region, + String serviceName + ) { Objects.requireNonNull(sessionToken); - final var accessKeyPredicate = fixedAccessKey(accessKey); + final var accessKeyPredicate = fixedAccessKey(accessKey, region, serviceName); return (authorizationHeader, sessionTokenHeader) -> accessKeyPredicate.test(authorizationHeader, sessionTokenHeader) && sessionToken.equals(sessionTokenHeader); } diff --git a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixture.java b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixture.java index 538c57bc2bdea..2cb9627d4a087 100644 --- a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixture.java +++ b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixture.java @@ -33,7 +33,7 @@ public class S3HttpFixture extends ExternalResource { private final BiPredicate authorizationPredicate; public S3HttpFixture(boolean enabled) { - this(enabled, "bucket", "base_path_integration_tests", fixedAccessKey("s3_test_access_key")); + this(enabled, "bucket", "base_path_integration_tests", fixedAccessKey("s3_test_access_key", "*", "s3")); } public S3HttpFixture(boolean enabled, String bucket, String basePath, BiPredicate authorizationPredicate) { diff --git a/x-pack/plugin/searchable-snapshots/qa/s3/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/s3/S3SearchableSnapshotsCredentialsReloadIT.java b/x-pack/plugin/searchable-snapshots/qa/s3/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/s3/S3SearchableSnapshotsCredentialsReloadIT.java index bb5df5d37dba3..5889140bf2bab 100644 --- a/x-pack/plugin/searchable-snapshots/qa/s3/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/s3/S3SearchableSnapshotsCredentialsReloadIT.java +++ b/x-pack/plugin/searchable-snapshots/qa/s3/src/javaRestTest/java/org/elasticsearch/xpack/searchablesnapshots/s3/S3SearchableSnapshotsCredentialsReloadIT.java @@ -47,7 +47,12 @@ public class S3SearchableSnapshotsCredentialsReloadIT extends ESRestTestCase { private static volatile String repositoryAccessKey; - public static final S3HttpFixture s3Fixture = new S3HttpFixture(true, BUCKET, BASE_PATH, mutableAccessKey(() -> repositoryAccessKey)); + public static final S3HttpFixture s3Fixture = new S3HttpFixture( + true, + BUCKET, + BASE_PATH, + mutableAccessKey(() -> repositoryAccessKey, "*", "s3") + ); private static final MutableSettingsProvider keystoreSettings = new MutableSettingsProvider();