Skip to content

Commit

Permalink
[s3-repository] Support generating AWS role session name in case it's…
Browse files Browse the repository at this point in the history
… not provided (#86255) (#86502)

The AWS SDK actually doesn't require the session name to be set and generates one if
it's not provided via the AWS_ROLE_SESSION_NAME environment variable.

See #52625
  • Loading branch information
arteam authored May 6, 2022
1 parent fb6b2b9 commit dc1435c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/86255.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 86255
summary: "[s3-repository] Support generating AWS role session name in case it's not provided"
area: Snapshot/Restore
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
import java.util.Map;
import java.util.Objects;

Expand Down Expand Up @@ -71,7 +72,8 @@ class S3Service implements Closeable {
webIdentityTokenCredentialsProvider = new CustomWebIdentityTokenCredentialsProvider(
environment,
System::getenv,
System::getProperty
System::getProperty,
Clock.systemUTC()
);
}

Expand Down Expand Up @@ -294,7 +296,8 @@ static class CustomWebIdentityTokenCredentialsProvider implements AWSCredentials
CustomWebIdentityTokenCredentialsProvider(
Environment environment,
SystemEnvironment systemEnvironment,
JvmEnvironment jvmEnvironment
JvmEnvironment jvmEnvironment,
Clock clock
) {
// Check whether the original environment variable exists. If it doesn't,
// the system doesn't support AWS web identity tokens
Expand All @@ -315,14 +318,19 @@ static class CustomWebIdentityTokenCredentialsProvider implements AWSCredentials
throw new IllegalStateException("Unable to read a Web Identity Token symlink in the config directory");
}
String roleArn = systemEnvironment.getEnv(AWS_ROLE_ARN_ENV_VAR);
String roleSessionName = systemEnvironment.getEnv(AWS_ROLE_SESSION_NAME_ENV_VAR);
if (roleArn == null || roleSessionName == null) {
if (roleArn == null) {
LOGGER.warn(
"Unable to use a web identity token for authentication. The AWS_WEB_IDENTITY_TOKEN_FILE environment "
+ "variable is set, but either AWS_ROLE_ARN or AWS_ROLE_SESSION_NAME are missing"
+ "variable is set, but either AWS_ROLE_ARN is missing"
);
return;
}
String roleSessionName = Objects.requireNonNullElseGet(
systemEnvironment.getEnv(AWS_ROLE_SESSION_NAME_ENV_VAR),
// Mimic the default behaviour of the AWS SDK in case the session name is not set
// See `com.amazonaws.auth.WebIdentityTokenCredentialsProvider#45`
() -> "aws-sdk-java-" + clock.millis()
);
AWSSecurityTokenServiceClientBuilder stsClientBuilder = AWSSecurityTokenServiceClient.builder();

// Custom system property used for specifying a mocked version of the STS for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,35 @@

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

public class CustomWebIdentityTokenCredentialsProviderTests extends ESTestCase {

private static final String ROLE_ARN = "arn:aws:iam::123456789012:role/FederatedWebIdentityRole";
private static final String ROLE_NAME = "sts-fixture-test";
private static final String ROLE_NAME = "aws-sdk-java-1651084775908";

@SuppressForbidden(reason = "HTTP server is used for testing")
public void testCreateWebIdentityTokenCredentialsProvider() throws Exception {
HttpServer httpServer = MockHttpServer.createHttp(new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0), 0);
httpServer.createContext("/", exchange -> {
try (exchange) {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
Map<String, String> params = Arrays.stream(body.split("&"))
.map(e -> e.split("="))
.collect(Collectors.toMap(e -> e[0], e -> URLDecoder.decode(e[1], StandardCharsets.UTF_8)));
assertEquals(ROLE_NAME, params.get("RoleSessionName"));

exchange.getResponseHeaders().add("Content-Type", "text/xml; charset=UTF-8");
byte[] response = """
<AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
Expand Down Expand Up @@ -85,9 +97,7 @@ public void testCreateWebIdentityTokenCredentialsProvider() throws Exception {
"AWS_WEB_IDENTITY_TOKEN_FILE",
"/var/run/secrets/eks.amazonaws.com/serviceaccount/token",
"AWS_ROLE_ARN",
ROLE_ARN,
"AWS_ROLE_SESSION_NAME",
ROLE_NAME
ROLE_ARN
);
Map<String, String> systemProperties = Map.of(
"com.amazonaws.sdk.stsMetadataServiceEndpointOverride",
Expand All @@ -96,7 +106,8 @@ public void testCreateWebIdentityTokenCredentialsProvider() throws Exception {
var webIdentityTokenCredentialsProvider = new S3Service.CustomWebIdentityTokenCredentialsProvider(
environment,
environmentVariables::get,
systemProperties::getOrDefault
systemProperties::getOrDefault,
Clock.fixed(Instant.ofEpochMilli(1651084775908L), ZoneOffset.UTC)
);
try {
AWSCredentials credentials = S3Service.buildCredentials(
Expand Down

0 comments on commit dc1435c

Please sign in to comment.