|
| 1 | +# AWS Credential Chain |
| 2 | + |
| 3 | +Assembles an ordered AWS credential provider chain from SPI-discovered |
| 4 | +providers. Provides the infrastructure for modular credential resolution. |
| 5 | + |
| 6 | +## Dependency |
| 7 | + |
| 8 | +```kotlin |
| 9 | +dependencies { |
| 10 | + implementation("software.amazon.smithy.java:aws-credential-chain:1.1.0") |
| 11 | +} |
| 12 | +``` |
| 13 | + |
| 14 | +## Wiring to a client |
| 15 | + |
| 16 | +### Automatic (codegen) |
| 17 | + |
| 18 | +Services modeled with `@aws.auth#sigv4` or `@aws.auth#sigv4a` automatically get |
| 19 | +`AwsCredentialChainPlugin` added as a default plugin during code generation. |
| 20 | +No manual wiring is needed: just add the provider modules you need to your |
| 21 | +runtime dependencies. |
| 22 | + |
| 23 | +### Manual |
| 24 | + |
| 25 | +```java |
| 26 | +var client = MyClient.builder() |
| 27 | + .addPlugin(new AwsCredentialChainPlugin()) |
| 28 | + .build(); |
| 29 | +``` |
| 30 | + |
| 31 | +The plugin registers the credential chain as the client's identity resolver and |
| 32 | +adds an interceptor that invalidates cached credentials on auth failures |
| 33 | +(`ExpiredToken`, `InvalidToken`, `AuthFailure`). |
| 34 | + |
| 35 | +## Standalone usage |
| 36 | + |
| 37 | +```java |
| 38 | +try (AwsCredentialChain chain = AwsCredentialChain.create()) { |
| 39 | + IdentityResult<AwsCredentialsIdentity> result = chain.resolveIdentity(context); |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +## How it works |
| 44 | + |
| 45 | +The chain discovers `AwsCredentialProvider` implementations via ServiceLoader, |
| 46 | +orders them by builtin enum slots, and tries each in order until one succeeds. |
| 47 | + |
| 48 | +## Builtin slots (in priority order) |
| 49 | + |
| 50 | +1. `CODE` — programmatic |
| 51 | +2. `JAVA_SYSTEM_PROPERTIES` — `aws.accessKeyId` |
| 52 | +3. `ENVIRONMENT` — `AWS_ACCESS_KEY_ID` |
| 53 | +4. `WEB_IDENTITY_TOKEN_ENV` — `AWS_WEB_IDENTITY_TOKEN_FILE` + `AWS_ROLE_ARN` |
| 54 | +5. `SHARED_CONFIG` — `~/.aws/config` / `~/.aws/credentials` |
| 55 | +6. `ECS_CONTAINER` — `AWS_CONTAINER_CREDENTIALS_FULL_URI` |
| 56 | +7. `EC2_INSTANCE_METADATA` — IMDS |
| 57 | + |
| 58 | +## Ordering |
| 59 | + |
| 60 | +Providers position themselves relative to builtin slots using |
| 61 | +`OrderingConstraint`: |
| 62 | + |
| 63 | +- `Builtin(slot)` — claims a builtin slot (one provider per slot). Only one |
| 64 | + provider can claim a builtin. Not all builtins have to be claimed. |
| 65 | +- `Before(slot)` — inserts before the given slot's position |
| 66 | +- `After(slot)` — inserts after the given slot's position |
| 67 | + |
| 68 | +Before/After reference enum values only, so cycles are impossible. If the |
| 69 | +referenced slot has no registered provider, the custom provider is placed |
| 70 | +where that slot would be in enum order. |
| 71 | + |
| 72 | +## Adding a custom provider |
| 73 | + |
| 74 | +```java |
| 75 | +public class MyProvider implements AwsCredentialProvider { |
| 76 | + @Override |
| 77 | + public String name() { |
| 78 | + return "MyCustomProvider"; |
| 79 | + } |
| 80 | + |
| 81 | + @Override |
| 82 | + public OrderingConstraint ordering() { |
| 83 | + return new OrderingConstraint.After(BuiltinProvider.SHARED_CONFIG); |
| 84 | + } |
| 85 | + |
| 86 | + @Override |
| 87 | + public IdentityResolver<AwsCredentialsIdentity> create(ProviderContext ctx) { |
| 88 | + return new MyResolver(); |
| 89 | + } |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +Register in `META-INF/services/software.amazon.smithy.java.aws.credentials.chain.AwsCredentialProvider`. |
0 commit comments