Skip to content

Add modular AWS credential resolution#1172

Open
mtdowling wants to merge 3 commits intomainfrom
aws-auth
Open

Add modular AWS credential resolution#1172
mtdowling wants to merge 3 commits intomainfrom
aws-auth

Conversation

@mtdowling
Copy link
Copy Markdown
Member

@mtdowling mtdowling commented May 7, 2026

Adds support for loading AWS credentials from shared config/credentials files and assembling them into a pluggable credential provider chain.

New modules:

  • aws-config: SEP-conformant INI parser, profile data model, AwsConfigCredentialSource sealed types, handler SPI with ServiceLoader discovery, and built-in handlers for static keys, session keys, and credential_process.
  • aws-credential-chain: Credential provider chain with builtin slots, Before/After relative ordering, SPI-based provider discovery, cheap environment detection, and actionable error messages when implementation modules are missing.

Changes to existing modules:

  • auth-api: Add CachingIdentityResolver with async background refresh, static stability support, injectable Clock and ScheduledExecutorService. Add invalidate() default method to IdentityResolver interface. Will be used by STS, SSO, etc.
  • aws-client-core: Add AwsCredentialChainPlugin ClientPlugin, register EnvironmentCredentialProvider and SystemPropertiesCredentialProvider as chain sources via SPI. Both now read AWS_ACCOUNT_ID / aws.accountId per the account ID SEP.
  • settings.gradle.kts: Include new modules.

Architecture overview:

  • Data model (aws-config) is separated from resolution policy (chain).
  • Credential sources are detected cheaply from profile properties without needing implementation modules (STS, SSO, IMDS).
  • Handlers are discovered via ServiceLoader; missing handlers produce errors naming the dependency to add.
  • Chain ordering uses a fixed enum for builtins and simple Before/After insertion for third-party providers.
  • CachingIdentityResolver provides background refresh with a shared ScheduledExecutorService passed via ProviderContext.
  • invalidate() propagates through the chain to force credential refresh on auth failures.

TODO items: add SSO, STS, ECS, etc.


Here's an example of how to use shared credentials and IMDS:

// build.gradle.kts
dependencies {
    implementation("software.amazon.smithy.java:aws-client-core:1.1.0")
    implementation("software.amazon.smithy.java:aws-config:1.1.0")
    implementation("software.amazon.smithy.java:aws-credentials-imds:1.1.0")
}

Then you just apply the AwsCredentialChainPlugin.

var client = CoffeeShopClient.builder()
        .addPlugin(new AwsCredentialChainPlugin())
        .build();

With the above configuration, credentials are resolved automatically by checking the following in order:

  1. JVM system properties (aws.accessKeyId)
  2. Environment variables (AWS_ACCESS_KEY_ID)
  3. Config file (~/.aws/credentials or ~/.aws/config)
  4. EC2 IMDS (if on EC2)

Let's say only need environment variables because you're running on Lambda. Then you just need to configure aws-client-core, which automatically resolves environment variables (you'd still apply AwsCredentialChainPlugin).

dependencies {
    implementation("software.amazon.smithy.java:aws-client-core:1.1.0")
}

mtdowling added 2 commits May 7, 2026 17:40
Adds support for loading AWS credentials from shared config/credentials
files and assembling them into a pluggable credential provider chain.

New modules:
- aws-config: SEP-conformant INI parser, profile data model,
  AwsConfigCredentialSource sealed types, handler SPI with ServiceLoader
  discovery, and built-in handlers for static keys, session keys, and
  credential_process.
- aws-credential-chain: Credential provider chain with builtin slots,
  Before/After relative ordering, SPI-based provider discovery, cheap
  environment detection, and actionable error messages when
  implementation modules are missing.

Changes to existing modules:
- auth-api: Add CachingIdentityResolver with async background refresh,
  static stability support, injectable Clock and
  ScheduledExecutorService. Add invalidate() default method to
  IdentityResolver interface. Will be used by STS, SSO, etc.
- aws-client-core: Add AwsCredentialChainPlugin ClientPlugin, register
  EnvironmentCredentialProvider and SystemPropertiesCredentialProvider
  as chain sources via SPI. Both now read AWS_ACCOUNT_ID / aws.accountId
  per the account ID SEP.
- settings.gradle.kts: Include new modules.

Architecture overview:
- Data model (aws-config) is separated from resolution policy (chain).
- Credential sources are detected cheaply from profile properties
  without needing implementation modules (STS, SSO, IMDS).
- Handlers are discovered via ServiceLoader; missing handlers produce
  errors naming the dependency to add.
- Chain ordering uses a fixed enum for builtins and simple Before/After
  insertion for third-party providers.
- CachingIdentityResolver provides background refresh with a shared
  ScheduledExecutorService passed via ProviderContext.
- invalidate() propagates through the chain to force credential refresh
  on auth failures.

TODO items: add SSO, STS, IMDS, ECS, etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant