Skip to content

Commit

Permalink
Set region for the STS client via privileged calls in AWS SDK (elasti…
Browse files Browse the repository at this point in the history
…c#102230)

Unfortunately, `AWSSecurityTokenServiceClientBuilder#setRegion` is not just a setter on the builder. It looks up the region by its name which lazily initializes some regional configuration. As a result, the call with an access denied error, because the caller doesn't have permission to call `accessDeclaredMembers` in some Jackson internals.

This bug wasn't caught by the `CustomWebIdentityTokenCredentialsProviderTests#testSupportRegionalizedEndpoints` test because it's under with the test framework that does allow naked reflection calls.

We fix that in two ways:

*  Make sure withRegion call is privileged
*  Eagerly lookup region metadata in `S3Repository` 

Fixes elastic#102173
  • Loading branch information
arteam committed Nov 16, 2023
1 parent 9844195 commit 0a8665c
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 1 deletion.
6 changes: 6 additions & 0 deletions docs/changelog/102230.yaml
@@ -0,0 +1,6 @@
pr: 102230
summary: Set region for the STS client via privileged calls in AWS SDK
area: Snapshot/Restore
type: bug
issues:
- 102173
35 changes: 35 additions & 0 deletions modules/repository-s3/build.gradle
Expand Up @@ -322,6 +322,41 @@ if (useFixture) {
}
}
// Sanity test for STS Regional Endpoints
if (useFixture) {
tasks.register("yamlRestTestRegionalSTS", RestIntegTestTask.class) {
description = "Runs tests with the Regional STS Endpoint"
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
SourceSet yamlRestTestSourceSet = sourceSets.getByName(LegacyYamlRestTestPlugin.SOURCE_SET_NAME)
setTestClassesDirs(yamlRestTestSourceSet.getOutput().getClassesDirs())
setClasspath(yamlRestTestSourceSet.getRuntimeClasspath())
// Run just the basic sanity test to make sure ES starts up and loads the S3 repository with
// a regional endpoint without an error. It would be great to make actual requests against
// a test fixture, but setting the region means using a production endpoint
systemProperty 'tests.rest.blacklist', [
'repository_s3/20_repository_permanent_credentials/*',
'repository_s3/30_repository_temporary_credentials/*',
'repository_s3/40_repository_ec2_credentials/*',
'repository_s3/50_repository_ecs_credentials/*',
'repository_s3/60_repository_sts_credentials/*'
].join(",")
}
tasks.named("check").configure { dependsOn("yamlRestTestRegionalSTS") }
testClusters.matching { it.name == "yamlRestTestRegionalSTS" }.configureEach {
module tasks.named("explodedBundlePlugin")
File awsWebIdentityTokenExternalLocation = file('src/test/resources/aws-web-identity-token-file')
extraConfigFile 'repository-s3/aws-web-identity-token-file', awsWebIdentityTokenExternalLocation
environment 'AWS_WEB_IDENTITY_TOKEN_FILE', "$awsWebIdentityTokenExternalLocation"
environment 'AWS_ROLE_ARN', 'arn:aws:iam::123456789012:role/FederatedWebIdentityRole'
environment 'AWS_ROLE_SESSION_NAME', 'sts-fixture-test'
// Force the repository to set a regional production endpoint
environment 'AWS_STS_REGIONAL_ENDPOINTS', 'regional'
environment 'AWS_REGION', 'ap-southeast-2'
}
}
// 3rd Party Tests
TaskProvider s3ThirdPartyTest = tasks.register("s3ThirdPartyTest", Test) {
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
Expand Down
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.repositories.s3;

import com.amazonaws.regions.RegionUtils;
import com.amazonaws.util.json.Jackson;

import org.apache.lucene.util.SetOnce;
Expand Down Expand Up @@ -60,6 +61,8 @@ public class S3RepositoryPlugin extends Plugin implements RepositoryPlugin, Relo
// ClientConfiguration clinit has some classloader problems
// TODO: fix that
Class.forName("com.amazonaws.ClientConfiguration");
// Pre-load region metadata to avoid looking them up dynamically without privileges enabled
RegionUtils.initialize();
} catch (final ClassNotFoundException e) {
throw new RuntimeException(e);
}
Expand Down
Expand Up @@ -370,7 +370,7 @@ static class CustomWebIdentityTokenCredentialsProvider implements AWSCredentials
// https://github.com/aws/amazon-eks-pod-identity-webhook/pull/41
stsRegion = systemEnvironment.getEnv(SDKGlobalConfiguration.AWS_REGION_ENV_VAR);
if (stsRegion != null) {
stsClientBuilder.withRegion(stsRegion);
SocketAccess.doPrivilegedVoid(() -> stsClientBuilder.withRegion(stsRegion));
} else {
LOGGER.warn("Unable to use regional STS endpoints because the AWS_REGION environment variable is not set");
}
Expand Down

0 comments on commit 0a8665c

Please sign in to comment.