Skip to content

AppConfigPropertySource reload fails with "Token not valid" #1697

Description

@nickt-2007

Type: Bug

Component: AppConfig

Describe the bug

Using Spring Cloud AWS 4.1.0 (io.awspring.cloud:spring-cloud-aws-app-config:4.1.0, io.awspring.cloud:spring-cloud-aws-autoconfigure:4.1.0) with AppConfig reload enabled:

spring:
  cloud:
    aws:
      appconfig:
        reload:
          strategy: refresh
          period: 10s
  config:
    import:
      - aws-appconfig:APP#ENV#PROFILE

AppConfigPropertySource stores the AppConfigData session token in a plain String sessionToken field. init() rotates it correctly:

GetLatestConfigurationResponse response = this.source.getLatestConfiguration(request);
...
sessionToken = response.nextPollConfigurationToken();

However, PollingAwsPropertySourceChangeDetector.executeCycle() never calls init() on the actual AppConfigPropertySource instance registered in the Environment. Every polling cycle it does:

AwsPropertySource copy = source.copy();
copy.init();
if (changed(source, copy)) {
    reloadProperties();
}

AppConfigPropertySource.copy() constructs a new instance by copying the current sessionToken value:

public AppConfigPropertySource copy() {
    return new AppConfigPropertySource(context, appConfigClient, sessionToken, new LinkedHashMap<>(properties));
}

So copy.init() rotates the token and receives the new nextPollConfigurationToken, but that new token is only stored on the copy, which is discarded at the end of the cycle. The original
instance living in the Environment keeps the same, never-refreshed token forever.

When token is expired, will get exception:

software.amazon.awssdk.services.appconfigdata.model.BadRequestException: Token not valid (Service: AppConfigData, Status Code: 400, Request ID: ...)
      at software.amazon.awssdk.services.appconfigdata.DefaultAppConfigDataClient.getLatestConfiguration
      at io.awspring.cloud.appconfig.AppConfigPropertySource.init
      at io.awspring.cloud.autoconfigure.config.reload.PollingAwsPropertySourceChangeDetector.executeCycle

Suggested fix: share the mutable token state between the original AwsPropertySource and every instance produced by copy(), instead of copying the token value. E.g. change sessionToken from
String to AtomicReference<String>, and have copy() pass the same AtomicReference instance to the new copy:

private final AtomicReference<String> sessionToken;

public AppConfigPropertySource copy() {
    return new AppConfigPropertySource(context, appConfigClient, sessionToken, new LinkedHashMap<>(properties));
}

This way, whichever instance (original or copy) successfully rotates the token, all instances sharing that reference see the up-to-date token on the next cycle, while properties (used for change
detection) stays independently copied so changed(source, copy) still works correctly.

Sample

  1. Configure an app with spring.cloud.aws.appconfig.reload.strategy=refresh and a short period (e.g. 10s), importing any AppConfig configuration profile.
  2. Wait until token expire.
  3. Observe: throws BadRequestException: Token not valid, repeating on every subsequent cycle.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions