Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html">AWS v4 Signatures</a>
* @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<String, String> fixedAccessKey(String accessKey) {
return mutableAccessKey(() -> accessKey);
public static BiPredicate<String, String> 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 <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html">AWS v4 Signatures</a>
* @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<String, String> mutableAccessKey(Supplier<String> accessKeySupplier) {
return (authorizationHeader, sessionTokenHeader) -> authorizationHeader != null
&& authorizationHeader.contains(accessKeySupplier.get());
public static BiPredicate<String, String> mutableAccessKey(Supplier<String> 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put this in the method comment, since callers use it: it's a feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep fair point

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 <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html">AWS v4 Signatures</a>
* @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<String, String> fixedAccessKeyAndToken(String accessKey, String sessionToken) {
public static BiPredicate<String, String> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class S3HttpFixture extends ExternalResource {
private final BiPredicate<String, String> 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<String, String> authorizationPredicate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down