Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StsAssumeRoleWithWebIdentityCredentialsProvider does not call refreshRequest #5709

Open
1 task
paul-gardiner opened this issue Nov 12, 2024 · 2 comments
Open
1 task
Assignees
Labels
bug This issue is a bug. p2 This is a standard priority issue

Comments

@paul-gardiner
Copy link

Describe the bug

I am using StsAssumeRoleWithWebIdentityCredentialsProvider to assume an AWS role using a token created on Azure AD/Entra. When the AWS token expires, it will get a new token as long as the WebIdentityToken from Entra has not expired. Once the WebIdentityToken expires, the next refresh to get an AWS token results in an ExpiredTokenException.

Regression Issue

  • Select this option if this issue appears to be a regression.

Expected Behavior

When refreshing the AWS token, I expected refreshRequest to be called, which would update the WebIdentityToken. However, it is not called.

Current Behavior

s.a.a.s.s.m.ExpiredTokenException: Token expired: current date/time 1731098245 must be before the expiration date/time 1731095240 (Service: Sts, Status Code: 400, Request ID: 22679931-6a1d-4db3-abd0-a189de181809)
at s.a.a.c.i.h.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
at s.a.a.c.i.h.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
at s.a.a.c.i.h.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
at s.a.a.c.i.h.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
at s.a.a.c.i.h.p.s.HandleResponseStage.execute(HandleResponseStage.java:50)
at s.a.a.c.i.h.p.s.HandleResponseStage.execute(HandleResponseStage.java:38)
at s.a.a.c.i.h.p.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at s.a.a.c.i.h.p.s.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:74)
at s.a.a.c.i.h.p.s.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:43)
at s.a.a.c.i.h.p.s.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:79)
at s.a.a.c.i.h.p.s.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:41)
at s.a.a.c.i.h.p.s.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:55)
at s.a.a.c.i.h.p.s.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:39)
at s.a.a.c.i.h.p.s.RetryableStage2.executeRequest(RetryableStage2.java:93)
at s.a.a.c.i.h.p.s.RetryableStage2.execute(RetryableStage2.java:56)
at s.a.a.c.i.h.p.s.RetryableStage2.execute(RetryableStage2.java:36)
at s.a.a.c.i.h.p.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at s.a.a.c.i.h.StreamManagingStage.execute(StreamManagingStage.java:53)
at s.a.a.c.i.h.StreamManagingStage.execute(StreamManagingStage.java:35)
at s.a.a.c.i.h.p.s.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:82)
at s.a.a.c.i.h.p.s.Api...

Reproduction Steps

Following is the config class (springboot) that creates the StsAssumeRoleWithWebIdentityCredentialsProvider bean.

@Configuration
@Slf4j
class AwsAssumeRoleConfig {

  @Value("${application.aws-role-session-duration}")
  private int sessionDuration;
  @Value("${application.aws-assumed-role-arn}")
  private String assumedRoleArn;

  @Bean
  StsAssumeRoleWithWebIdentityCredentialsProvider assumeRoleWithWebIdentityCredentialsProvider(
      StsClient stsClient, EntraTokenProvider entraTokenProvider) {
    String sessionName = "cct-" + UUID.randomUUID().toString();
    log.info("Creating StsAssumeRole provider for role: {} with session name {} with duration {}",
        assumedRoleArn, sessionName,
        sessionDuration);

    return StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
        .stsClient(stsClient)
        .asyncCredentialUpdateEnabled(true)
        .refreshRequest(assumeRoleRequest -> {
          log.info("entra token requested for assume role");
          OAuth2AccessToken token = entraTokenProvider.getAccessToken();
          if (log.isDebugEnabled()) {
            log.debug("Token received from entra: {}***********",
                token.getTokenValue().substring(0, 5));
          } else {
            log.info("Token received from entra, length {}", token.getTokenValue().length());
          }
          assumeRoleRequest.webIdentityToken(token.getTokenValue());
          assumeRoleRequest.roleArn(assumedRoleArn);
          assumeRoleRequest.roleSessionName(sessionName);
          assumeRoleRequest.durationSeconds(sessionDuration);
        })
        .build();
  }

  @SuppressWarnings("java:S6242")
  @Bean
  StsClient stsClient() {
    return StsClient.builder()
        .region(Region.CA_CENTRAL_1)

        .build();
  }
}

Possible Solution

No response

Additional Information/Context

Dependencies are:

implementation 'org.springframework.cloud:spring-cloud-stream-binder-kinesis:4.0.4'
implementation 'org.apache.httpcomponents.client5:httpclient5'
implementation 'software.amazon.awssdk:kinesis:2.29.1'
implementation 'software.amazon.awssdk:dynamodb:2.29.1'
implementation 'software.amazon.awssdk:cloudwatch:2.29.1'
implementation 'software.amazon.awssdk:sts:2.29.1'
implementation 'org.springframework.security:spring-security-oauth2-client'
implementation 'com.azure.spring:spring-cloud-azure-stream-binder-eventhubs:5.17.1'
implementation 'com.google.protobuf:protobuf-java:4.28.3'

AWS Java SDK version used

2.29.1

JDK version used

OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)

Operating System and version

Oracle Linux Server 8.10

@paul-gardiner paul-gardiner added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Nov 12, 2024
@bhoradc
Copy link

bhoradc commented Jan 6, 2025

Hello @paul-gardiner,

Thank you for reporting the issue.

Firstly, can you please confirm if the following best describes the issue you're experiencing?

  1. When the AWS temporary credentials is about to expire, the refreshRequest lambda is invoked to obtain a new web identity token and request new AWS credentials from the AWS STS.
  2. However, when the web identity token itself expires, the refreshRequest lambda is not being called, leading to an ExpiredTokenException when attempting to refresh the AWS credentials.

If the above understanding is correct, then this looks an expected behaviour with the StsAssumeRoleWithWebIdentityCredentialsProvider. As I believe the refreshRequest lambda is supposed to be called when the temporary AWS credentials need to be refreshed, regardless of the state of the web identity token.

When the refreshRequest lambda is invoked, isn't the EntraTokenProvider resulting in a fresh web identity token each time, irrespective of the previous token expiration status?

Can you confirm that the EntraTokenProvider implementation is correctly providing a fresh web identity token when called within the refreshRequest lambda, even after the previous token has expired? And if possible, enable the debug logs(redact sensitive info) and share with us?

If my understanding of this problem has any deviation, please provide any additional information or clarification that might help to better understand and troubleshoot this issue.

Regards
Chaitanya

@bhoradc bhoradc added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days. p2 This is a standard priority issue and removed needs-triage This issue or PR still needs to be triaged. labels Jan 6, 2025
@bhoradc bhoradc self-assigned this Jan 6, 2025
@paul-gardiner
Copy link
Author

Not quite. When the AWS credentials expire, if the web identity token is still valid, everything is fine, but if it has expired, it isn't refreshed. My expectation is that StsAssumeRoleWithWebIdentityCredentialsProvider will refresh the web identity token before it expires.

I have worked around the issue by wrapping the StsClient, and then in AssumeRoleWithWebIdentityResponse assumeRoleWithWebIdentity(AssumeRoleWithWebIdentityRequest), I create a new AssumeRoleWithWebIdentityRequest, with a new web identity token. This works, but is a bit messy.

It has been a couple of months, but I'll see if I can get a version going with the issue, and turn on debug.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days. label Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. p2 This is a standard priority issue
Projects
None yet
Development

No branches or pull requests

2 participants