Skip to content

Add modular AWS credential resolution#1172

Open
mtdowling wants to merge 13 commits into
mainfrom
aws-auth
Open

Add modular AWS credential resolution#1172
mtdowling wants to merge 13 commits into
mainfrom
aws-auth

Conversation

@mtdowling
Copy link
Copy Markdown
Member

@mtdowling mtdowling commented May 7, 2026

Add modular credential chain with pluggable provider discovery

Adds a modular AWS credential provider chain that separates credential detection from resolution, enabling independent artifact composition.

New modules:

  • aws-config: SEP-conformant INI parser, AwsProfileFile, AwsProfile, AwsConfigCredentialSource sealed types. Standalone module with no chain dependency.
  • aws-credential-chain: CredentialChain, ChainIdentityProvider SPI, ChainSetup, StandardProvider enum with expanded profile-source slots, OrderingConstraint (Standard/Before/After), SharedConfigProvider, StaticKeysHandler, SessionKeysHandler, CredentialProcessHandler.
  • aws-credentials-imds: IMDSv2 credential provider with static stability, extended/legacy API fallback, config-based disable.

Changes to existing modules:

  • auth-api: Add CachingIdentityResolver with async background refresh, static stability, injectable Clock/ScheduledExecutorService. Add invalidate() default method to IdentityResolver.
  • aws-client-core: Add AwsCredentialChainPlugin, auth-failure interceptor, EnvironmentCredentialProvider and
    SystemPropertiesCredentialProvider (both terminal — stop chain assembly when credentials are present).
  • settings.gradle.kts: Include new modules.

Architecture:

  • One interface (ChainIdentityProvider), one SPI, void create() method.
  • Providers are sorted by ordering() then called in order with a shared mutable ChainSetup. They call setup.addResolver() to register, or setup.addTerminalResolver() to register and stop assembly.
  • StandardProvider enum encodes the full chain precedence including per-profile-source slots, matching the Credentials Provider Chain Search Precedence SEP exactly.
  • SharedConfigProvider parses config files and sets profile on setup; downstream profile providers read from setup.profile().
  • Terminal resolvers short-circuit assembly (env vars set → config never parsed, IMDS never created).
  • Actionable errors name the missing module when a source is detected but no provider claims its slot.
  • CachingIdentityResolver provides background refresh; invalidate() propagates through the chain to clear caches on auth failures.

TODO: STS, SSO, ECS, Login providers.


Example usage:

// build.gradle.kts
dependencies {
    implementation("software.amazon.smithy.java:aws-client-core:1.1.0")
    implementation("software.amazon.smithy.java:aws-credential-chain:1.1.0")
    implementation("software.amazon.smithy.java:aws-credentials-imds:1.1.0")
}
var client = CoffeeShopClient.builder()
        .addPlugin(new AwsCredentialChainPlugin())
        .build();

Credentials resolve automatically in order:

  1. JVM system properties (aws.accessKeyId) — terminal
  2. Environment variables (AWS_ACCESS_KEY_ID) — terminal
  3. Config file static/session keys — terminal
  4. Config file credential_process
  5. EC2 IMDS (if aws-credentials-imds is added)

On Lambda, only aws-client-core is needed (env vars are terminal, nothing else is constructed):

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

mtdowling added 8 commits May 11, 2026 15:59
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.
Allowing custom provider relative positioning around only builtins
simplifies the design, removes the possibility of cycles, and removes
the need for a topo sort. Also removing aliases.
Automatically add credential chain runtime plugin if AWS auth is
used.
@mtdowling mtdowling marked this pull request as draft May 12, 2026 14:59
@mtdowling mtdowling marked this pull request as ready for review May 12, 2026 19:54
mtdowling added 2 commits May 12, 2026 16:39
Reduces chain to a single, flat chain of fixed slots, including
config based credentials.
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