Skip to content

Commit b6f2129

Browse files
committed
Migrate EKS authentication from AWS 1.x -> AWS 2.x
1 parent 8163087 commit b6f2129

File tree

6 files changed

+68
-52
lines changed

6 files changed

+68
-52
lines changed

examples/examples-release-latest/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@
9090
<version>${spring.boot.version}</version>
9191
</dependency>
9292
<dependency>
93-
<groupId>com.amazonaws</groupId>
94-
<artifactId>aws-java-sdk-sts</artifactId>
93+
<groupId>software.amazon.awssdk</groupId>
94+
<artifactId>sts</artifactId>
9595
</dependency>
9696

9797
</dependencies>
@@ -116,4 +116,4 @@
116116
</plugins>
117117
</build>
118118

119-
</project>
119+
</project>

examples/examples-release-latest/src/main/java/io/kubernetes/client/examples/EKSAuthenticationExample.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
*/
1313
package io.kubernetes.client.examples;
1414

15-
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
16-
import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider;
1715
import io.kubernetes.client.openapi.ApiClient;
1816
import io.kubernetes.client.openapi.ApiException;
1917
import io.kubernetes.client.openapi.models.VersionInfo;
@@ -22,6 +20,9 @@
2220
import io.kubernetes.client.util.version.Version;
2321

2422
import java.io.IOException;
23+
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
24+
import software.amazon.awssdk.services.sts.StsClient;
25+
import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider;
2526

2627
public class EKSAuthenticationExample {
2728
public static void main(String[] args) throws IOException, ApiException {
@@ -37,10 +38,14 @@ public static void main(String[] args) throws IOException, ApiException {
3738
// EKS cluster name.
3839
String clusterName = "test-2";
3940

40-
STSAssumeRoleSessionCredentialsProvider credProvider = new STSAssumeRoleSessionCredentialsProvider(
41-
new DefaultAWSCredentialsProviderChain().getCredentials(),
42-
roleArn,
43-
roleSessionName);
41+
StsClient stsClient = StsClient.builder()
42+
.credentialsProvider(DefaultCredentialsProvider.builder().build())
43+
.build();
44+
45+
StsAssumeRoleCredentialsProvider credProvider = StsAssumeRoleCredentialsProvider.builder()
46+
.stsClient(stsClient)
47+
.refreshRequest(r -> r.roleArn(roleArn).roleSessionName(roleSessionName))
48+
.build();
4449

4550
ApiClient apiClient = ClientBuilder.standard()
4651
.setAuthentication(new EKSAuthentication(credProvider, region, clusterName))

pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
https://issues.apache.org/jira/browse/MNG-5632. Therefore, we specify
7676
optional dependencies here to manage them in a single location. -->
7777
<prometheus.client.optional>true</prometheus.client.optional>
78-
<com.amazonaws.aws-java-sdk-sts.optional>true</com.amazonaws.aws-java-sdk-sts.optional>
78+
<software.amazon.awssdk.sts.optional>true</software.amazon.awssdk.sts.optional>
7979
<com.google.auth.google-auth-library-oauth2-http.optional>true</com.google.auth.google-auth-library-oauth2-http.optional>
8080
<org.springframework.boot.spring-boot-actuator.optional>true</org.springframework.boot.spring-boot-actuator.optional>
8181

@@ -150,9 +150,9 @@
150150
<version>${bouncycastle.version}</version>
151151
</dependency>
152152
<dependency>
153-
<groupId>com.amazonaws</groupId>
154-
<artifactId>aws-java-sdk-sts</artifactId>
155-
<version>1.12.787</version>
153+
<groupId>software.amazon.awssdk</groupId>
154+
<artifactId>sts</artifactId>
155+
<version>2.31.70</version>
156156
</dependency>
157157
<dependency>
158158
<groupId>com.google.protobuf</groupId>

util/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@
6060
<artifactId>bcpkix-jdk18on</artifactId>
6161
</dependency>
6262
<dependency>
63-
<groupId>com.amazonaws</groupId>
64-
<artifactId>aws-java-sdk-sts</artifactId>
65-
<optional>${com.amazonaws.aws-java-sdk-sts.optional}</optional>
63+
<groupId>software.amazon.awssdk</groupId>
64+
<artifactId>sts</artifactId>
65+
<optional>${software.amazon.awssdk.sts.optional}</optional>
6666
</dependency>
6767
<dependency>
6868
<groupId>ch.qos.logback</groupId>

util/src/main/java/io/kubernetes/client/util/credentials/EKSAuthentication.java

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,23 @@
1212
*/
1313
package io.kubernetes.client.util.credentials;
1414

15-
import com.amazonaws.DefaultRequest;
16-
import com.amazonaws.auth.AWS4Signer;
17-
import com.amazonaws.auth.AWSSessionCredentialsProvider;
18-
import com.amazonaws.http.HttpMethodName;
19-
import com.amazonaws.services.securitytoken.model.GetCallerIdentityRequest;
20-
import com.amazonaws.util.RuntimeHttpUtils;
2115
import io.kubernetes.client.openapi.ApiClient;
2216
import org.slf4j.Logger;
2317
import org.slf4j.LoggerFactory;
18+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
19+
import software.amazon.awssdk.http.SdkHttpMethod;
20+
import software.amazon.awssdk.http.SdkHttpRequest;
21+
import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner;
22+
import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
23+
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
24+
import software.amazon.awssdk.utils.http.SdkHttpUtils;
2425

2526
import java.net.URI;
2627
import java.nio.charset.StandardCharsets;
27-
import java.time.Clock;
28+
import java.time.Duration;
2829
import java.time.Instant;
2930
import java.time.temporal.ChronoUnit;
3031
import java.util.Base64;
31-
import java.util.Date;
3232

3333
/**
3434
* EKS cluster authentication which generates a bearer token from AWS AK/SK. It doesn't require an "aws"
@@ -45,11 +45,11 @@ public class EKSAuthentication implements Authentication {
4545
* @param region the region where EKS cluster at
4646
* @param clusterName the EKS cluster name
4747
*/
48-
public EKSAuthentication(AWSSessionCredentialsProvider provider, String region, String clusterName) {
48+
public EKSAuthentication(AwsCredentialsProvider provider, String region, String clusterName) {
4949
this(provider, region, clusterName, MAX_EXPIRY_SECONDS);
5050
}
5151

52-
public EKSAuthentication(AWSSessionCredentialsProvider provider, String region, String clusterName, int expirySeconds) {
52+
public EKSAuthentication(AwsCredentialsProvider provider, String region, String clusterName, int expirySeconds) {
5353
this.provider = provider;
5454
this.region = region;
5555
this.clusterName = clusterName;
@@ -61,7 +61,7 @@ public EKSAuthentication(AWSSessionCredentialsProvider provider, String region,
6161
}
6262

6363
private static final int MAX_EXPIRY_SECONDS = 60 * 15;
64-
private final AWSSessionCredentialsProvider provider;
64+
private final AwsCredentialsProvider provider;
6565
private final String region;
6666
private final String clusterName;
6767
private final URI stsEndpoint;
@@ -70,30 +70,41 @@ public EKSAuthentication(AWSSessionCredentialsProvider provider, String region,
7070

7171
@Override
7272
public void provide(ApiClient client) {
73-
DefaultRequest<GetCallerIdentityRequest> defaultRequest =
74-
new DefaultRequest<>(new GetCallerIdentityRequest(), "sts");
75-
defaultRequest.setResourcePath("/");
76-
defaultRequest.setEndpoint(stsEndpoint);
77-
defaultRequest.setHttpMethod(HttpMethodName.GET);
78-
defaultRequest.addParameter("Action", "GetCallerIdentity");
79-
defaultRequest.addParameter("Version", "2011-06-15");
80-
defaultRequest.addHeader("x-k8s-aws-id", clusterName);
81-
AWS4Signer signer = new AWS4Signer();
82-
Date expirationTime = new Date(Clock.systemDefaultZone().millis() + 60 * 1000);
83-
signer.setServiceName("sts");
84-
signer.presignRequest(
85-
defaultRequest,
86-
this.provider.getCredentials(),
87-
expirationTime);
88-
String encodedUrl =
89-
Base64.getUrlEncoder()
90-
.withoutPadding()
91-
.encodeToString( RuntimeHttpUtils.convertRequestToUrl(
92-
defaultRequest, true, false).toString()
93-
.getBytes(StandardCharsets.UTF_8));
73+
SdkHttpRequest httpRequest = generateStsRequest();
74+
String presignedUrl = requestToPresignedUrl(httpRequest);
75+
String encodedUrl = presignedUrlToEncodedUrl(presignedUrl);
9476
String token = "k8s-aws-v1." + encodedUrl;
9577
client.setApiKeyPrefix("Bearer");
9678
client.setApiKey(token);
9779
log.info("Generated BEARER token for ApiClient, expiring at {}", Instant.now().plus(expirySeconds, ChronoUnit.SECONDS));
9880
}
81+
82+
private static String presignedUrlToEncodedUrl(String presignedUrl) {
83+
return Base64.getUrlEncoder()
84+
.withoutPadding()
85+
.encodeToString(SdkHttpUtils.urlEncodeIgnoreSlashes(presignedUrl).getBytes(StandardCharsets.UTF_8));
86+
}
87+
88+
private SdkHttpRequest generateStsRequest() {
89+
return SdkHttpRequest.builder()
90+
.uri(stsEndpoint)
91+
.putRawQueryParameter("Version", "2011-06-15")
92+
.putRawQueryParameter("Action", "GetCallerIdentity")
93+
.method(SdkHttpMethod.GET)
94+
.putHeader("x-k8s-aws-id", clusterName)
95+
.build();
96+
}
97+
98+
private String requestToPresignedUrl(SdkHttpRequest httpRequest) {
99+
AwsV4HttpSigner signer = AwsV4HttpSigner.create();
100+
SignedRequest signedRequest =
101+
signer.sign(r -> r.identity(this.provider.resolveCredentials())
102+
.request(httpRequest)
103+
.putProperty(AwsV4HttpSigner.SERVICE_SIGNING_NAME, "sts")
104+
.putProperty(AwsV4HttpSigner.REGION_NAME, region)
105+
.putProperty(AwsV4HttpSigner.AUTH_LOCATION, AwsV4HttpSigner.AuthLocation.QUERY_STRING)
106+
.putProperty(AwsV4HttpSigner.EXPIRATION_DURATION, Duration.of(60, ChronoUnit.SECONDS)));
107+
SdkHttpRequest request = signedRequest.request();
108+
return request.getUri().toString();
109+
}
99110
}

util/src/test/java/io/kubernetes/client/util/credentials/EKSAuthenticationTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
*/
1313
package io.kubernetes.client.util.credentials;
1414

15-
import com.amazonaws.auth.AWSSessionCredentialsProvider;
16-
import com.amazonaws.auth.BasicSessionCredentials;
1715
import io.kubernetes.client.openapi.ApiClient;
1816
import org.junit.jupiter.api.Test;
1917
import org.junit.jupiter.api.extension.ExtendWith;
2018
import org.mockito.Mock;
2119
import org.mockito.junit.jupiter.MockitoExtension;
20+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
21+
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
2222

2323
import static org.mockito.ArgumentMatchers.anyString;
2424
import static org.mockito.Mockito.verify;
@@ -28,7 +28,7 @@
2828
class EKSAuthenticationTest {
2929

3030
@Mock
31-
private AWSSessionCredentialsProvider provider;
31+
private AwsCredentialsProvider provider;
3232

3333
@Mock
3434
private ApiClient apiClient;
@@ -39,7 +39,7 @@ class EKSAuthenticationTest {
3939

4040
@Test
4141
void provideApiClient() {
42-
when(provider.getCredentials()).thenReturn(new BasicSessionCredentials("ak", "sk", "session"));
42+
when(provider.resolveCredentials()).thenReturn(AwsSessionCredentials.create("ak", "sk", "session"));
4343
EKSAuthentication authentication = new EKSAuthentication(provider, region, clusterName);
4444
authentication.provide(apiClient);
4545
verify(apiClient).setApiKey(anyString());

0 commit comments

Comments
 (0)