Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ and building services. These examples can be used as a template for a new projec
## Usage

> [!WARNING]
> Smithy-Java only supports **Java 17** or later. Older Java versions are not supported.
> Smithy-Java only supports **Java 21** or later. Older Java versions are not supported.

### Codegen (Gradle)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package software.amazon.smithy.java.auth.api;

import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.auth.api.identity.Identity;
import software.amazon.smithy.java.context.Context;

Expand All @@ -31,7 +30,7 @@ private NullSigner() {}
* @return the request as-is.
*/
@Override
public CompletableFuture<Object> sign(Object request, Identity identity, Context properties) {
return CompletableFuture.completedFuture(request);
public Object sign(Object request, Identity identity, Context properties) {
return request;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package software.amazon.smithy.java.auth.api;

import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.auth.api.identity.Identity;
import software.amazon.smithy.java.context.Context;

Expand All @@ -25,7 +24,7 @@ public interface Signer<RequestT, IdentityT extends Identity> extends AutoClosea
* @param properties Signing properties.
* @return the signed request.
*/
CompletableFuture<RequestT> sign(RequestT request, IdentityT identity, Context properties);
RequestT sign(RequestT request, IdentityT identity, Context properties);

@SuppressWarnings("unchecked")
static <RequestT, IdentityT extends Identity> Signer<RequestT, IdentityT> nullSigner() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package software.amazon.smithy.java.auth.api.identity;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.context.Context;

/**
Expand All @@ -20,9 +19,9 @@ public interface IdentityResolver<IdentityT extends Identity> {
* error string. Unexpected errors like malformed input or networking errors are allowed to throw exceptions.
*
* @param requestProperties The request properties used to resolve an Identity.
* @return a CompletableFuture for the resolved identity result.
* @return the resolved identity result.
*/
CompletableFuture<IdentityResult<IdentityT>> resolveIdentity(Context requestProperties);
IdentityResult<IdentityT> resolveIdentity(Context requestProperties);

/**
* Retrieve the class of the identity resolved by this identity resolver.
Expand All @@ -42,7 +41,8 @@ static <I extends Identity> IdentityResolver<I> chain(List<IdentityResolver<I>>
}

/**
* Create an implementation of {@link IdentityResolver} that returns a specific, pre-defined instance of {@link Identity}.
* Create an implementation of {@link IdentityResolver} that returns a specific, pre-defined instance of
* {@link Identity}.
*/
static <I extends Identity> IdentityResolver<I> of(I identity) {
return new StaticIdentityResolver<>(identity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.context.Context;

final class IdentityResolverChain<IdentityT extends Identity> implements IdentityResolver<IdentityT> {
Expand All @@ -29,35 +28,15 @@ public Class<IdentityT> identityType() {
}

@Override
public CompletableFuture<IdentityResult<IdentityT>> resolveIdentity(Context requestProperties) {
public IdentityResult<IdentityT> resolveIdentity(Context requestProperties) {
List<IdentityResult<?>> errors = new ArrayList<>();
return executeChain(resolvers.get(0), requestProperties, errors, 0);
}

private CompletableFuture<IdentityResult<IdentityT>> executeChain(
IdentityResolver<IdentityT> resolver,
Context requestProperties,
List<IdentityResult<?>> errors,
int idx
) {
var result = resolver.resolveIdentity(requestProperties);
if (idx + 1 < resolvers.size()) {
var nextResolver = resolvers.get(idx + 1);
return result.thenCompose(ir -> {
if (ir.error() != null) {
errors.add(ir);
return executeChain(nextResolver, requestProperties, errors, idx + 1);
}
return CompletableFuture.completedFuture(ir);
});
}

return result.thenApply(ir -> {
if (ir.error() != null) {
errors.add(ir);
return IdentityResult.ofError(IdentityResolverChain.class, "Attempted resolvers: " + errors);
for (IdentityResolver<IdentityT> resolver : resolvers) {
IdentityResult<IdentityT> result = resolver.resolveIdentity(requestProperties);
if (result.error() == null) {
return result;
}
return ir;
});
errors.add(result);
}
return IdentityResult.ofError(IdentityResolverChain.class, "Attempted resolvers: " + errors);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@
package software.amazon.smithy.java.auth.api.identity;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.context.Context;

final class StaticIdentityResolver<IdentityT extends Identity> implements IdentityResolver<IdentityT> {

private final IdentityT identity;
private final CompletableFuture<IdentityResult<IdentityT>> result;
private final IdentityResult<IdentityT> result;

public StaticIdentityResolver(IdentityT identity) {
this.identity = Objects.requireNonNull(identity);
this.result = CompletableFuture.completedFuture(IdentityResult.of(identity));
this.result = IdentityResult.of(identity);
}

@Override
public CompletableFuture<IdentityResult<IdentityT>> resolveIdentity(Context requestProperties) {
public IdentityResult<IdentityT> resolveIdentity(Context requestProperties) {
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public static Flow.Publisher<ByteBuffer> bodyForEventStreaming(
return EventStreamFrameEncodingProcessor.create(eventStream, eventStreamEncodingFactory, input);
}

public static <O extends SerializableStruct> CompletableFuture<O> deserializeResponse(
// TODO: Make more synchronous
public static <O extends SerializableStruct> O deserializeResponse(
EventDecoderFactory<AwsEventFrame> eventDecoderFactory,
DataStream bodyDataStream
) {
Expand Down Expand Up @@ -63,7 +64,7 @@ public void onComplete() {
}
});

return result;
return result.join();
}

private static Schema streamingMember(Schema schema) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@

package software.amazon.smithy.java.aws.client.auth.scheme.sigv4;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
Expand Down Expand Up @@ -110,9 +108,9 @@ public void setup() throws Exception {
}

@Benchmark
public void sign() throws IOException, ExecutionException, InterruptedException {
public void sign() {
if (!skipTest) {
signer.sign(request, TEST_IDENTITY, TEST_PROPERTIES).get();
signer.sign(request, TEST_IDENTITY, TEST_PROPERTIES);
} else {
System.out.println("Skipping benchmark on Windows");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import software.amazon.smithy.java.auth.api.Signer;
Expand Down Expand Up @@ -98,11 +97,7 @@ public void close() {
}

@Override
public CompletableFuture<HttpRequest> sign(
HttpRequest request,
AwsCredentialsIdentity identity,
Context properties
) {
public HttpRequest sign(HttpRequest request, AwsCredentialsIdentity identity, Context properties) {
var region = properties.expect(SigV4Settings.REGION);
var name = properties.expect(SigV4Settings.SIGNING_NAME);
var clock = properties.getOrDefault(SigV4Settings.CLOCK, Clock.systemUTC());
Expand All @@ -111,32 +106,31 @@ public CompletableFuture<HttpRequest> sign(
// TODO: Support chunk encoding
// TODO: support UNSIGNED

return getPayloadHash(request.body()).thenApply(payloadHash -> {
var signedHeaders = createSignedHeaders(
request.method(),
request.uri(),
request.headers(),
payloadHash,
region,
name,
clock.instant(),
identity.accessKeyId(),
identity.secretAccessKey(),
identity.sessionToken(),
!request.body().hasKnownLength());
// Don't let the cached buffers grow too large.
var sb = signingResources.sb;
if (sb.length() > BUFFER_SIZE) {
sb.setLength(BUFFER_SIZE);
sb.trimToSize();
}
sb.setLength(0);
return request.toBuilder().headers(HttpHeaders.of(signedHeaders)).build();
});
var payloadHash = getPayloadHash(request.body());
var signedHeaders = createSignedHeaders(
request.method(),
request.uri(),
request.headers(),
payloadHash,
region,
name,
clock.instant(),
identity.accessKeyId(),
identity.secretAccessKey(),
identity.sessionToken(),
!request.body().hasKnownLength());
// Don't let the cached buffers grow too large.
var sb = signingResources.sb;
if (sb.length() > BUFFER_SIZE) {
sb.setLength(BUFFER_SIZE);
sb.trimToSize();
}
sb.setLength(0);
return request.toBuilder().headers(HttpHeaders.of(signedHeaders)).build();
}

private CompletableFuture<String> getPayloadHash(DataStream dataStream) {
return dataStream.asByteBuffer().thenApply(this::hexHash);
private String getPayloadHash(DataStream dataStream) {
return hexHash(dataStream.waitForByteBuffer());
}

private String hexHash(ByteBuffer bytes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private static HttpRequest parseRequest(String fileName) {
Result createResult(
Signer<HttpRequest, AwsCredentialsIdentity> signer
) throws ExecutionException, InterruptedException {
var signedRequest = signer.sign(request, context.identity, context.properties).get();
var signedRequest = signer.sign(request, context.identity, context.properties);
boolean isValid = signedRequest.headers().equals(expected.headers())
&& signedRequest.uri().equals(expected.uri())
&& signedRequest.method().equals(expected.method());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.client.http.AmznErrorHeaderExtractor;
import software.amazon.smithy.java.client.http.HttpClientProtocol;
import software.amazon.smithy.java.client.http.HttpErrorDeserializer;
Expand Down Expand Up @@ -82,7 +81,7 @@ public <I extends SerializableStruct, O extends SerializableStruct> HttpRequest
}

@Override
public <I extends SerializableStruct, O extends SerializableStruct> CompletableFuture<O> deserializeResponse(
public <I extends SerializableStruct, O extends SerializableStruct> O deserializeResponse(
ApiOperation<I, O> operation,
Context context,
TypeRegistry typeRegistry,
Expand All @@ -91,21 +90,18 @@ public <I extends SerializableStruct, O extends SerializableStruct> CompletableF
) {
// Is it an error?
if (response.statusCode() != 200) {
return errorDeserializer
.createError(context, operation.schema().id(), typeRegistry, response)
.thenApply(e -> {
throw e;
});
throw errorDeserializer.createError(context, operation.schema().id(), typeRegistry, response);
}

var builder = operation.outputBuilder();
var content = response.body();

// If the payload is empty, then use "{}" as the default empty payload.
if (content.contentLength() == 0) {
return CompletableFuture.completedFuture(codec.deserializeShape(EMPTY_PAYLOAD, builder));
return codec.deserializeShape(EMPTY_PAYLOAD, builder);
}

return content.asByteBuffer().thenApply(bytes -> codec.deserializeShape(bytes, builder));
var bytes = content.waitForByteBuffer();
return codec.deserializeShape(bytes, builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package software.amazon.smithy.java.aws.client.core.identity;

import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.auth.api.identity.IdentityResult;
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsIdentity;
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsResolver;
Expand Down Expand Up @@ -33,16 +32,15 @@ public final class EnvironmentVariableIdentityResolver implements AwsCredentials
+ "AWS_SECRET_ACCESS_KEY environment variables";

@Override
public CompletableFuture<IdentityResult<AwsCredentialsIdentity>> resolveIdentity(Context requestProperties) {
public IdentityResult<AwsCredentialsIdentity> resolveIdentity(Context requestProperties) {
String accessKey = System.getenv(ACCESS_KEY_PROPERTY);
String secretKey = System.getenv(SECRET_KEY_PROPERTY);
String sessionToken = System.getenv(SESSION_TOKEN_PROPERTY);

if (accessKey == null || secretKey == null) {
return CompletableFuture.completedFuture(IdentityResult.ofError(getClass(), ERROR_MESSAGE));
return IdentityResult.ofError(getClass(), ERROR_MESSAGE);
}

return CompletableFuture.completedFuture(
IdentityResult.of(AwsCredentialsIdentity.create(accessKey, secretKey, sessionToken)));
return IdentityResult.of(AwsCredentialsIdentity.create(accessKey, secretKey, sessionToken));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package software.amazon.smithy.java.aws.client.core.identity;

import java.util.concurrent.CompletableFuture;
import software.amazon.smithy.java.auth.api.identity.IdentityResult;
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsIdentity;
import software.amazon.smithy.java.aws.auth.api.identity.AwsCredentialsResolver;
Expand Down Expand Up @@ -35,20 +34,15 @@ public final class SystemPropertiesIdentityResolver implements AwsCredentialsRes
+ "aws.secretAccessKey system properties";

@Override
public CompletableFuture<IdentityResult<AwsCredentialsIdentity>> resolveIdentity(Context requestProperties) {
public IdentityResult<AwsCredentialsIdentity> resolveIdentity(Context requestProperties) {
String accessKey = System.getProperty(ACCESS_KEY_PROPERTY);
String secretKey = System.getProperty(SECRET_KEY_PROPERTY);
String sessionToken = System.getProperty(SESSION_TOKEN_PROPERTY);

if (accessKey != null && secretKey != null) {
return CompletableFuture.completedFuture(
IdentityResult.of(
AwsCredentialsIdentity.create(
accessKey,
secretKey,
sessionToken)));
return IdentityResult.of(AwsCredentialsIdentity.create(accessKey, secretKey, sessionToken));
}

return CompletableFuture.completedFuture(IdentityResult.ofError(getClass(), ERROR_MESSAGE));
return IdentityResult.ofError(getClass(), ERROR_MESSAGE);
}
}
Loading