diff --git a/core/http-auth-spi/pom.xml b/core/http-auth-spi/pom.xml new file mode 100644 index 000000000000..416e3228a055 --- /dev/null +++ b/core/http-auth-spi/pom.xml @@ -0,0 +1,86 @@ + + + + + 4.0.0 + + + software.amazon.awssdk + core + 2.20.47-SNAPSHOT + + + http-auth-spi + AWS Java SDK :: HTTP Auth SPI + + The AWS SDK for Java - HTTP Auth SPI module contains the interfaces for authentication that are used by other + modules in the library. + + https://aws.amazon.com/sdkforjava + + + + software.amazon.awssdk + annotations + ${awsjavasdk.version} + + + software.amazon.awssdk + utils + ${awsjavasdk.version} + + + software.amazon.awssdk + http-client-spi + ${awsjavasdk.version} + + + org.reactivestreams + reactive-streams + ${reactive-streams.version} + + + + org.junit.jupiter + junit-jupiter + test + + + nl.jqno.equalsverifier + equalsverifier + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.http.auth.spi + + + + + + + + diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java new file mode 100644 index 000000000000..c67b0c4a5bf7 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSignRequest.java @@ -0,0 +1,83 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi; + +import java.util.Optional; +import software.amazon.awssdk.annotations.Immutable; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.auth.spi.internal.DefaultHttpSignRequest; +import software.amazon.awssdk.utils.builder.SdkBuilder; + +/** + * Represents a request to be signed by {@link HttpSigner}. + * + * @param The type of payload of this request. + */ +@SdkPublicApi +@Immutable +@ThreadSafe +public interface HttpSignRequest { + + /** + * Get a new builder for creating a {@link HttpSignRequest}. + */ + static Builder builder(Class payloadType) { + return new DefaultHttpSignRequest.BuilderImpl(payloadType); + } + + /** + * Returns the type of the payload. + */ + Class payloadType(); + + /** + * Returns the HTTP request object, without the request body payload. + */ + SdkHttpRequest request(); + + /** + * Returns the body payload of the request. A payload is optional. By default, the payload will be empty. + */ + Optional payload(); + + /** + * Returns the property that the {@link HttpSigner} can use during signing. + */ + T property(SignerProperty property); + + /** + * A builder for a {@link HttpSignRequest}. + */ + interface Builder extends SdkBuilder, HttpSignRequest> { + + /** + * Set the HTTP request object, without the request body payload. + */ + Builder request(SdkHttpRequest request); + + /** + * Set the body payload of the request. A payload is optional. By default, the payload will be empty. + */ + Builder payload(PayloadT payload); + + /** + * Set a property that the {@link HttpSigner} can use during signing. + */ + Builder putProperty(SignerProperty key, T value); + } +} diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java new file mode 100644 index 000000000000..60596518403f --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/HttpSigner.java @@ -0,0 +1,45 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi; + +import java.nio.ByteBuffer; +import org.reactivestreams.Publisher; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.http.ContentStreamProvider; + +/** + * Interface for the process of modifying a request destined for a service so that the service can authenticate the SDK + * customer’s identity + */ +@SdkPublicApi +public interface HttpSigner { + + /** + * Method that takes in a request and returns a signed version of the request. + * + * @param request The request to sign, with sync payload + * @return A signed version of the input request + */ + SignedHttpRequest sign(HttpSignRequest request); + + /** + * Method that takes in a request and returns a signed version of the request. + * + * @param request The request to sign, with async payload + * @return A signed version of the input request + */ + SignedHttpRequest> signAsync(HttpSignRequest> request); +} diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java new file mode 100644 index 000000000000..380fdff00f46 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignedHttpRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi; + +import java.util.Optional; +import software.amazon.awssdk.annotations.Immutable; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.auth.spi.internal.DefaultSignedHttpRequest; +import software.amazon.awssdk.utils.builder.SdkBuilder; + +/** + * Represents a request that has been signed by {@link HttpSigner}. + * + * @param The type of payload of this request. + */ +@SdkPublicApi +@Immutable +@ThreadSafe +public interface SignedHttpRequest { + + /** + * Get a new builder for creating a {@link SignedHttpRequest}. + */ + static Builder builder(Class payloadType) { + return new DefaultSignedHttpRequest.BuilderImpl(payloadType); + } + + /** + * Returns the type of the payload. + */ + Class payloadType(); + + /** + * Returns the HTTP request object, without the request body payload. + */ + SdkHttpRequest request(); + + /** + * Returns the body payload of the request. A payload is optional. By default, the payload will be empty. + */ + Optional payload(); + + /** + * A builder for a {@link SignedHttpRequest}. + */ + interface Builder extends SdkBuilder, SignedHttpRequest> { + + /** + * Set the HTTP request object, without the request body payload. + */ + Builder request(SdkHttpRequest request); + + /** + * Set the body payload of the request. A payload is optional. By default, the payload will be empty. + */ + Builder payload(PayloadT payload); + } +} diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java new file mode 100644 index 000000000000..7a424a71bdb8 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/SignerProperty.java @@ -0,0 +1,78 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi; + +import java.util.Objects; +import software.amazon.awssdk.annotations.Immutable; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; + +/** + * A strongly-typed property for input to an {@link HttpSigner}. + * @param The type of the attribute. + */ +@SdkPublicApi +@Immutable +@ThreadSafe +public final class SignerProperty { + private final Class clazz; + private final String name; + + private SignerProperty(Class clazz, String name) { + Validate.paramNotNull(clazz, "clazz"); + Validate.paramNotBlank(name, "name"); + + this.clazz = clazz; + this.name = name; + } + + public static SignerProperty create(Class clazz, String name) { + return new SignerProperty<>(clazz, name); + } + + @Override + public String toString() { + return ToString.builder("SignerProperty") + .add("clazz", clazz) + .add("name", name) + .build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SignerProperty that = (SignerProperty) o; + + return Objects.equals(clazz, that.clazz) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + Objects.hashCode(clazz); + hashCode = 31 * hashCode + Objects.hashCode(name); + return hashCode; + } +} diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java new file mode 100644 index 000000000000..d6a814daa262 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultHttpSignRequest.java @@ -0,0 +1,106 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi.internal; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.auth.spi.HttpSignRequest; +import software.amazon.awssdk.http.auth.spi.SignerProperty; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; + +@SdkInternalApi +public final class DefaultHttpSignRequest implements HttpSignRequest { + + private final Class payloadType; + private final SdkHttpRequest request; + private final PayloadT payload; + private final Map, Object> properties; + + DefaultHttpSignRequest(BuilderImpl builder) { + this.payloadType = Validate.paramNotNull(builder.payloadType, "payloadType"); + this.request = Validate.paramNotNull(builder.request, "request"); + this.payload = builder.payload; + this.properties = new HashMap<>(builder.properties); + } + + @Override + public Class payloadType() { + return payloadType; + } + + @Override + public SdkHttpRequest request() { + return request; + } + + @Override + public Optional payload() { + return payload == null ? Optional.empty() : Optional.of(payload); + } + + @Override + public T property(SignerProperty property) { + return (T) properties.get(property); + } + + @Override + public String toString() { + return ToString.builder("DefaultHttpSignRequest") + .add("payloadType", payloadType) + .add("request", request) + .add("properties", properties) + .build(); + } + + + public static final class BuilderImpl implements Builder { + private final Class payloadType; + private SdkHttpRequest request; + private PayloadT payload; + private final Map, Object> properties = new HashMap<>(); + + public BuilderImpl(Class payloadType) { + this.payloadType = payloadType; + } + + @Override + public Builder request(SdkHttpRequest request) { + this.request = request; + return this; + } + + @Override + public Builder payload(PayloadT payload) { + this.payload = payload; + return this; + } + + @Override + public Builder putProperty(SignerProperty key, T value) { + this.properties.put(key, value); + return this; + } + + @Override + public HttpSignRequest build() { + return new DefaultHttpSignRequest(this); + } + } +} diff --git a/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java new file mode 100644 index 000000000000..d256992ca226 --- /dev/null +++ b/core/http-auth-spi/src/main/java/software/amazon/awssdk/http/auth/spi/internal/DefaultSignedHttpRequest.java @@ -0,0 +1,88 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi.internal; + +import java.util.Optional; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.auth.spi.SignedHttpRequest; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; + +@SdkInternalApi +public final class DefaultSignedHttpRequest implements SignedHttpRequest { + + private final Class payloadType; + private final SdkHttpRequest request; + private final PayloadT payload; + + DefaultSignedHttpRequest(BuilderImpl builder) { + this.payloadType = Validate.paramNotNull(builder.payloadType, "payloadType"); + this.request = Validate.paramNotNull(builder.request, "request"); + this.payload = builder.payload; + } + + @Override + public Class payloadType() { + return payloadType; + } + + @Override + public SdkHttpRequest request() { + return request; + } + + @Override + public Optional payload() { + return payload == null ? Optional.empty() : Optional.of(payload); + } + + @Override + public String toString() { + return ToString.builder("DefaultSignedHttpRequest") + .add("payloadType", payloadType) + .add("request", request) + // .add("payload", payload) + .build(); + } + + public static final class BuilderImpl implements Builder { + private final Class payloadType; + private SdkHttpRequest request; + private PayloadT payload; + + public BuilderImpl(Class payloadType) { + this.payloadType = payloadType; + } + + @Override + public Builder request(SdkHttpRequest request) { + this.request = request; + return this; + } + + @Override + public Builder payload(PayloadT payload) { + this.payload = payload; + return this; + } + + @Override + public SignedHttpRequest build() { + return new DefaultSignedHttpRequest(this); + } + } +} diff --git a/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java b/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java new file mode 100644 index 000000000000..2c819ed6e188 --- /dev/null +++ b/core/http-auth-spi/src/test/java/software/amazon/awssdk/http/auth/spi/SignerPropertyTest.java @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.http.auth.spi; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; + +public class SignerPropertyTest { + + @Test + public void equalsHashcode() { + EqualsVerifier.forClass(SignerProperty.class) + .withNonnullFields("clazz", "name") + .verify(); + } +} diff --git a/core/pom.xml b/core/pom.xml index 575ef4238008..3f8e14089963 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -37,6 +37,7 @@ arns auth identity-spi + http-auth-spi auth-crt sdk-core aws-core