Skip to content

Commit 1410933

Browse files
committed
Add more sigv4/s3e cleanup
1 parent 4937c09 commit 1410933

21 files changed

Lines changed: 151 additions & 182 deletions

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/CreateSessionCallback.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* <pre>{@code
1717
* (bucket, baseCreds) -> {
1818
* var resp = s3Client.createSession(CreateSessionInput.builder().bucket(bucket).build());
19-
* return S3ExpressIdentity.create(
19+
* return AwsCredentialsIdentity.create(
2020
* resp.credentials().accessKeyId(),
2121
* resp.credentials().secretAccessKey(),
2222
* resp.credentials().sessionToken(),
@@ -29,5 +29,5 @@
2929
*/
3030
@FunctionalInterface
3131
public interface CreateSessionCallback {
32-
S3ExpressIdentity createSession(String bucket, AwsCredentialsIdentity baseCredentials);
32+
AwsCredentialsIdentity createSession(String bucket, AwsCredentialsIdentity baseCredentials);
3333
}

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3DisableExpressSessionAuthResolver.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import software.amazon.smithy.java.aws.config.AwsProfileFile;
1010
import software.amazon.smithy.java.client.core.ClientConfig;
1111
import software.amazon.smithy.java.client.core.ClientPlugin;
12-
import software.amazon.smithy.utils.SmithyUnstableApi;
1312

1413
/**
1514
* Plugin that resolves the {@code DisableS3ExpressSessionAuth} setting from environment and
@@ -29,13 +28,12 @@
2928
*
3029
* <p>Only {@code true} or {@code false} are accepted; anything else throws.
3130
*/
32-
@SmithyUnstableApi
33-
public final class S3DisableExpressSessionAuthResolver implements ClientPlugin {
31+
final class S3DisableExpressSessionAuthResolver implements ClientPlugin {
3432

3533
private static final String ENV_VAR = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH";
3634
private static final String PROFILE_PROPERTY = "s3_disable_express_session_auth";
3735

38-
public static final S3DisableExpressSessionAuthResolver INSTANCE = new S3DisableExpressSessionAuthResolver();
36+
static final S3DisableExpressSessionAuthResolver INSTANCE = new S3DisableExpressSessionAuthResolver();
3937

4038
private S3DisableExpressSessionAuthResolver() {}
4139

@@ -90,8 +88,7 @@ private static String profileName() {
9088
private static boolean parseBoolean(String value, String source) {
9189
if ("true".equalsIgnoreCase(value)) {
9290
return true;
93-
}
94-
if ("false".equalsIgnoreCase(value)) {
91+
} else if ("false".equalsIgnoreCase(value)) {
9592
return false;
9693
}
9794
throw new IllegalArgumentException(

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressAuthScheme.java

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import software.amazon.smithy.java.auth.api.identity.IdentityResolver;
1010
import software.amazon.smithy.java.auth.api.identity.IdentityResolvers;
1111
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsIdentity;
12+
import software.amazon.smithy.java.aws.client.auth.scheme.sigv4.SigV4Settings;
1213
import software.amazon.smithy.java.aws.client.core.settings.RegionSetting;
1314
import software.amazon.smithy.java.client.core.auth.scheme.AuthScheme;
1415
import software.amazon.smithy.java.context.Context;
@@ -18,19 +19,13 @@
1819
/**
1920
* Auth scheme for S3 Express directory-bucket data-plane requests.
2021
*
21-
* <p>The endpoint rules emit this auth scheme with the wire name {@code sigv4-s3express}, but
22-
* we expose it through smithy-java as {@code aws.auth#sigv4S3express} because Smithy ShapeIds
23-
* cannot contain hyphens. {@link
24-
* software.amazon.smithy.java.aws.client.rulesengine.AwsRulesExtension} translates the wire name
25-
* to this id when reading endpoint properties.
26-
*
2722
* <p>The identity is bucket-scoped session credentials returned by S3's {@code CreateSession}
2823
* API; the signer uses regular SigV4 with the session token sent as
2924
* {@code x-amz-s3session-token} (instead of {@code x-amz-security-token}).
3025
*/
31-
public final class S3ExpressAuthScheme implements AuthScheme<HttpRequest, S3ExpressIdentity> {
26+
final class S3ExpressAuthScheme implements AuthScheme<HttpRequest, AwsCredentialsIdentity> {
3227

33-
public static final ShapeId SCHEME_ID = ShapeId.from("aws.auth#sigv4S3express");
28+
static final ShapeId SCHEME_ID = ShapeId.from("aws.auth#sigv4S3express");
3429

3530
private static final String DEFAULT_SIGNING_NAME = "s3express";
3631

@@ -45,11 +40,11 @@ public final class S3ExpressAuthScheme implements AuthScheme<HttpRequest, S3Expr
4540
/**
4641
* @param createSession bridge to the user's S3 client's CreateSession operation.
4742
*/
48-
public S3ExpressAuthScheme(CreateSessionCallback createSession) {
43+
S3ExpressAuthScheme(CreateSessionCallback createSession) {
4944
this(DEFAULT_SIGNING_NAME, createSession);
5045
}
5146

52-
public S3ExpressAuthScheme(String signingName, CreateSessionCallback createSession) {
47+
S3ExpressAuthScheme(String signingName, CreateSessionCallback createSession) {
5348
this.signingName = signingName;
5449
this.createSession = createSession;
5550
}
@@ -65,8 +60,8 @@ public Class<HttpRequest> requestClass() {
6560
}
6661

6762
@Override
68-
public Class<S3ExpressIdentity> identityClass() {
69-
return S3ExpressIdentity.class;
63+
public Class<AwsCredentialsIdentity> identityClass() {
64+
return AwsCredentialsIdentity.class;
7065
}
7166

7267
@Override
@@ -75,11 +70,12 @@ public Context getSignerProperties(Context context) {
7570
// overrides from the resolved endpoint on top of these. The values stamped here are the
7671
// defaults the signer falls back to when the endpoint didn't override.
7772
var ctx = Context.create();
78-
ctx.put(software.amazon.smithy.java.aws.client.auth.scheme.sigv4.SigV4Settings.SIGNING_NAME, signingName);
73+
ctx.put(SigV4Settings.SIGNING_NAME, signingName);
74+
ctx.put(SigV4Settings.OMIT_SECURITY_TOKEN, true);
7975
ctx.put(RegionSetting.REGION, context.expect(RegionSetting.REGION));
80-
var clock = context.get(software.amazon.smithy.java.aws.client.auth.scheme.sigv4.SigV4Settings.CLOCK);
76+
var clock = context.get(SigV4Settings.CLOCK);
8177
if (clock != null) {
82-
ctx.put(software.amazon.smithy.java.aws.client.auth.scheme.sigv4.SigV4Settings.CLOCK, clock);
78+
ctx.put(SigV4Settings.CLOCK, clock);
8379
}
8480
return Context.unmodifiableView(ctx);
8581
}
@@ -107,32 +103,25 @@ public Context getIdentityProperties(Context context) {
107103
}
108104

109105
@Override
110-
public Signer<HttpRequest, S3ExpressIdentity> signer() {
106+
public Signer<HttpRequest, AwsCredentialsIdentity> signer() {
111107
return S3ExpressSigner.create(signingName);
112108
}
113109

114110
@Override
115-
public IdentityResolver<S3ExpressIdentity> identityResolver(IdentityResolvers resolvers) {
116-
// If the user registered their own S3ExpressIdentity resolver (e.g. via
117-
// ClientConfig.Builder#addIdentityResolver), prefer it. This is the override hook the
118-
// SEP recommends: customers can supply a custom CreateSession-compatible provider for
119-
// alternate caching, observability, or sourcing strategies.
120-
IdentityResolver<S3ExpressIdentity> override = resolvers.identityResolver(S3ExpressIdentity.class);
121-
if (override != null) {
122-
return override;
123-
}
124-
111+
public IdentityResolver<AwsCredentialsIdentity> identityResolver(IdentityResolvers resolvers) {
125112
IdentityResolver<AwsCredentialsIdentity> base = resolvers.identityResolver(AwsCredentialsIdentity.class);
126113
if (base == null) {
127114
return null;
128115
}
116+
129117
// Lock-free fast path for the common case where the same IdentityResolvers is passed
130118
// every call. If the base resolver instance changes (rare; it's a property of the
131119
// client's IdentityResolvers registry which doesn't change after build), rebuild.
132120
S3ExpressIdentityProvider local = provider;
133121
if (local != null && providerBase == base) {
134122
return local;
135123
}
124+
136125
synchronized (this) {
137126
if (provider == null || providerBase != base) {
138127
providerBase = base;

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressBucketInterceptor.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,21 @@
2020
*
2121
* <p>Runs in {@code readBeforeExecution}, before any auth-resolution stage.
2222
*/
23-
public final class S3ExpressBucketInterceptor implements ClientInterceptor {
23+
final class S3ExpressBucketInterceptor implements ClientInterceptor {
2424

25-
/** Singleton; the interceptor holds no state. */
26-
public static final S3ExpressBucketInterceptor INSTANCE = new S3ExpressBucketInterceptor();
25+
static final S3ExpressBucketInterceptor INSTANCE = new S3ExpressBucketInterceptor();
2726

2827
private S3ExpressBucketInterceptor() {}
2928

3029
@Override
3130
public void readBeforeExecution(InputHook<?, ?> hook) {
3231
var inputSchema = hook.operation().inputSchema();
3332
var bucketMember = inputSchema.member("Bucket");
34-
if (bucketMember == null) {
35-
return;
36-
}
37-
Object bucket = hook.input().getMemberValue(bucketMember);
38-
if (bucket instanceof String s && !s.isEmpty()) {
39-
hook.context().put(S3ExpressContext.BUCKET, s);
33+
if (bucketMember != null) {
34+
Object bucket = hook.input().getMemberValue(bucketMember);
35+
if (bucket instanceof String s && !s.isEmpty()) {
36+
hook.context().put(S3ExpressContext.BUCKET, s);
37+
}
4038
}
4139
}
4240
}

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressChecksumInterceptor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public <RequestT> RequestT modifyBeforeSigning(RequestHook<?, ?, RequestT> hook)
6161
if (hook.context().get(S3ExpressContext.BUCKET) == null) {
6262
return hook.request();
6363
}
64+
6465
if (!(hook.request() instanceof HttpRequest req)) {
6566
return hook.request();
6667
}
@@ -78,6 +79,7 @@ public <RequestT> RequestT modifyBeforeSigning(RequestHook<?, ?, RequestT> hook)
7879
if (body == null || body.contentLength() == 0) {
7980
return hook.request();
8081
}
82+
8183
if (!body.isReplayable() || !body.hasByteBuffer()) {
8284
// Streaming or non-replayable body — supporting it requires multi-chunk framing,
8385
// which AwsChunkedDataStream doesn't do yet. Skip the wrapping; SigV4 will fall
@@ -106,12 +108,14 @@ private static boolean alreadyHasChecksum(HttpRequest req) {
106108
if (req.headers().hasHeader(TRAILER_HEADER)) {
107109
return true;
108110
}
111+
109112
var present = new boolean[1];
110113
req.headers().forEachEntry(present, (state, name, value) -> {
111114
if (name.startsWith(CHECKSUM_HEADER_PREFIX)) {
112115
state[0] = true;
113116
}
114117
});
118+
115119
return present[0];
116120
}
117121
}

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressContext.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
* Context keys used by the S3 Express auth scheme to communicate per-call data.
1212
*/
1313
public final class S3ExpressContext {
14-
1514
/**
1615
* Bucket name on the in-flight request. Must be set by an interceptor that pulls the value
1716
* from the input shape before the auth pipeline asks for an identity. The

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressFeatureId.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
/**
1111
* Business-metric IDs published when this module's auth scheme runs successfully.
1212
*/
13-
public enum S3ExpressFeatureId implements FeatureId {
14-
13+
enum S3ExpressFeatureId implements FeatureId {
1514
/**
1615
* Emitted on every operation call that resolves a bucket-scoped S3 Express identity.
1716
*/

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressIdentity.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressIdentityCache.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.concurrent.locks.ReentrantLock;
1111
import java.util.function.Function;
1212
import software.amazon.smithy.java.auth.api.identity.CachingIdentityResolver;
13+
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsIdentity;
1314

1415
/**
1516
* Bucket-keyed cache of S3 Express identity resolvers.
@@ -44,13 +45,13 @@ final class S3ExpressIdentityCache implements AutoCloseable {
4445
private final ConcurrentHashMap<S3ExpressIdentityKey, Entry> entries = new ConcurrentHashMap<>();
4546
private final ReentrantLock writeLock = new ReentrantLock();
4647
private final AtomicLong tick = new AtomicLong();
47-
private final Function<S3ExpressIdentityKey, CachingIdentityResolver<S3ExpressIdentity>> factory;
48+
private final Function<S3ExpressIdentityKey, CachingIdentityResolver<AwsCredentialsIdentity>> factory;
4849

49-
S3ExpressIdentityCache(Function<S3ExpressIdentityKey, CachingIdentityResolver<S3ExpressIdentity>> factory) {
50+
S3ExpressIdentityCache(Function<S3ExpressIdentityKey, CachingIdentityResolver<AwsCredentialsIdentity>> factory) {
5051
this.factory = factory;
5152
}
5253

53-
CachingIdentityResolver<S3ExpressIdentity> get(S3ExpressIdentityKey key) {
54+
CachingIdentityResolver<AwsCredentialsIdentity> get(S3ExpressIdentityKey key) {
5455
Entry e = entries.get(key);
5556
if (e != null) {
5657
e.lastAccess = tick.incrementAndGet();
@@ -59,7 +60,7 @@ CachingIdentityResolver<S3ExpressIdentity> get(S3ExpressIdentityKey key) {
5960
return getOrCreate(key);
6061
}
6162

62-
private CachingIdentityResolver<S3ExpressIdentity> getOrCreate(S3ExpressIdentityKey key) {
63+
private CachingIdentityResolver<AwsCredentialsIdentity> getOrCreate(S3ExpressIdentityKey key) {
6364
writeLock.lock();
6465
try {
6566
Entry e = entries.get(key);
@@ -129,13 +130,13 @@ private static void closeQuietly(AutoCloseable c) {
129130
}
130131

131132
private static final class Entry {
132-
final CachingIdentityResolver<S3ExpressIdentity> resolver;
133+
final CachingIdentityResolver<AwsCredentialsIdentity> resolver;
133134

134135
// Volatile so concurrent readers see updated values; races on simultaneous writes are
135136
// benign (we only use this for approximate ordering of eviction).
136137
volatile long lastAccess;
137138

138-
Entry(CachingIdentityResolver<S3ExpressIdentity> resolver, long lastAccess) {
139+
Entry(CachingIdentityResolver<AwsCredentialsIdentity> resolver, long lastAccess) {
139140
this.resolver = resolver;
140141
this.lastAccess = lastAccess;
141142
}

aws/aws-sigv4-s3express/src/main/java/software/amazon/smithy/java/aws/client/auth/scheme/s3express/S3ExpressIdentityKey.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ final class S3ExpressIdentityKey {
3030
S3ExpressIdentityKey(String bucket, AwsCredentialsIdentity identity) {
3131
this.bucket = Objects.requireNonNull(bucket, "bucket");
3232
this.identity = Objects.requireNonNull(identity, "identity");
33-
this.hash = Objects.hash(
34-
bucket,
35-
identity.accessKeyId(),
36-
identity.secretAccessKey(),
37-
identity.sessionToken());
33+
int h = bucket.hashCode();
34+
h = 31 * h + identity.accessKeyId().hashCode();
35+
h = 31 * h + identity.secretAccessKey().hashCode();
36+
h = 31 * h + Objects.hashCode(identity.sessionToken());
37+
this.hash = h;
3838
}
3939

4040
String bucket() {

0 commit comments

Comments
 (0)