Skip to content

Commit

Permalink
Add test case for service with MultiAuth only and not using Sigv4
Browse files Browse the repository at this point in the history
  • Loading branch information
joviegas committed Jan 26, 2025
1 parent 81cca37 commit e5fb5b7
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public static Metadata constructMetadata(ServiceModel serviceModel,
.withJsonVersion(serviceMetadata.getJsonVersion())
.withEndpointPrefix(serviceMetadata.getEndpointPrefix())
.withSigningName(serviceMetadata.getSigningName())
.withAuthType(AuthType.fromValue(serviceMetadata.getSignatureVersion()))
.withAuthType(serviceMetadata.getSignatureVersion() !=null ?
AuthType.fromValue(serviceMetadata.getSignatureVersion()) : null)
.withUid(serviceMetadata.getUid())
.withServiceId(serviceMetadata.getServiceId())
.withSupportsH2(supportsH2(serviceMetadata))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.model.service.AuthType;
import software.amazon.awssdk.utils.CollectionUtils;

public final class AuthUtils {
private AuthUtils() {
Expand Down Expand Up @@ -76,6 +77,12 @@ private static boolean isServiceSigv4a(IntermediateModel model) {

private static boolean isServiceAwsAuthType(IntermediateModel model) {
AuthType authType = model.getMetadata().getAuthType();
if (authType == null && !CollectionUtils.isNullOrEmpty(model.getMetadata().getAuth())) {
return model.getMetadata().getAuth().stream()
.map(AuthType::value)
.map(AuthType::fromValue)
.anyMatch(AuthUtils::isAuthTypeAws);
}
return isAuthTypeAws(authType);
}

Expand All @@ -85,6 +92,7 @@ private static boolean isAuthTypeAws(AuthType authType) {
}

switch (authType) {
case V4A:
case V4:
case S3:
case S3V4:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"skipEndpointTestGeneration": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"version": "1.3",
"parameters": {
"Region": {
"builtIn": "AWS::Region",
"required": true,
"documentation": "The AWS region used to dispatch the request.",
"type": "String"
},
"ApiType": {
"required": true,
"documentation": "Parameter to determine whether current API is a control plane or dataplane API",
"type": "String"
}
},
"rules": [
{
"conditions": [
{
"fn": "stringEquals",
"argv": [
{
"ref": "ApiType"
},
"onlySigv4a"
]
}
],
"endpoint": {
"url": "https://only-region.{Region}.on.aws",
"properties": {
"authSchemes": [
{
"name": "sigv4a",
"signingName": "from-endpoint-params",
"signingRegionSet": [
"*"
]
}
]
},
"headers": {}
},
"type": "endpoint"
},
{
"conditions": [
{
"fn": "stringEquals",
"argv": [
{
"ref": "ApiType"
},
"NoEndpointSigningProperties"
]
}
],
"endpoint": {
"url": "https://only-region.{Region}.on.aws",
"properties": {
"authSchemes": [
]
},
"headers": {}
},
"type": "endpoint"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"testCases": [
],
"version": "1.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"version":"2.0",
"metadata":{
"apiVersion":"2016-03-11",
"endpointPrefix":"internalconfig",
"jsonVersion":"1.1",
"protocol":"rest-json",
"serviceAbbreviation":"AwsSigv4aMultiAuthService",
"serviceFullName":"AWS Multi Auth Service",
"serviceId":"Sigv4aauth",
"targetPrefix":"Sigv4aauth",
"auth":["aws.auth#sigv4a"],
"timestampFormat":"unixTimestamp",
"uid":"restjson-2016-03-11"
},
"operations":{
"simpleOperationWithNoEndpointParams":{
"name":"simpleOperationWithNoEndpointParams",
"http":{
"method":"POST",
"requestUri":"/2016-03-11/simpleOperationWithNoEndpointParams"
},
"input":{"shape":"sampleRequest"},
"staticContextParams":{
"ApiType":{"value":"NoEndpointSigningProperties"}
}
},
"simpleOperationWithEndpointParams":{
"name":"simpleOperationWithEndpointParams",
"http":{
"method":"POST",
"requestUri":"/2016-03-11/multiAuthWithOnlySigv4aAndSigv4"
},
"input":{"shape":"sampleRequest"},
"staticContextParams":{
"ApiType":{"value":"onlySigv4a"}
}
}
},
"shapes": {
"sampleRequest": {
"type": "structure",
"members": {
"StringMember": {
"shape": "String"
}
}
},
"String":{"type":"string"}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* 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.services.multiauth;

import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import java.util.concurrent.CompletableFuture;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner;
import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest;
import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest;
import software.amazon.awssdk.http.auth.spi.signer.BaseSignRequest;
import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
import software.amazon.awssdk.http.auth.spi.signer.SignRequest;
import software.amazon.awssdk.http.auth.spi.signer.SignedRequest;
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.identity.spi.IdentityProvider;
import software.amazon.awssdk.identity.spi.IdentityProviders;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sigv4aauth.Sigv4AauthClient;
import software.amazon.awssdk.testutils.EnvironmentVariableHelper;
import software.amazon.awssdk.utils.CompletableFutureUtils;

public class Sigv4aOnlyMultiAuthTest {


private static final String MOCK_HTTP_CLIENT_NAME = "MockHttpClient";
private static final String EXPECTED_EXCEPTION_MESSAGE = "expected exception";
private static final String CRT_DEPENDENCY_ERROR_MESSAGE =
"You must add a dependency on the 'software.amazon.awssdk:http-auth-aws-crt' module to enable the CRT-V4a signing "
+ "feature";

private final EnvironmentVariableHelper environmentVariableHelper = new EnvironmentVariableHelper();

@Mock
private SdkHttpClient mockHttpClient;

private static AuthScheme<?> authScheme(String schemeId, HttpSigner<AwsCredentialsIdentity> signer) {
return new AuthScheme<AwsCredentialsIdentity>() {
@Override
public String schemeId() {
return schemeId;
}

@Override
public IdentityProvider<AwsCredentialsIdentity> identityProvider(IdentityProviders providers) {
return providers.identityProvider(AwsCredentialsIdentity.class);
}

@Override
public HttpSigner<AwsCredentialsIdentity> signer() {
return signer;
}
};
}

@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
when(mockHttpClient.clientName()).thenReturn(MOCK_HTTP_CLIENT_NAME);
when(mockHttpClient.prepareRequest(any())).thenThrow(new RuntimeException(EXPECTED_EXCEPTION_MESSAGE));
}

@AfterEach
void tearDown() {
environmentVariableHelper.reset();
}

public static class CapturingSigner implements HttpSigner<AwsCredentialsIdentity> {
private BaseSignRequest<?, ?> request;

@Override
public SignedRequest sign(SignRequest<? extends AwsCredentialsIdentity> request) {
this.request = request;
throw new RuntimeException("stop");
}

@Override
public CompletableFuture<AsyncSignedRequest> signAsync(
AsyncSignRequest<? extends AwsCredentialsIdentity> request) {
this.request = request;
return CompletableFutureUtils.failedFuture(new RuntimeException("stop"));
}
}

@Nested
@DisplayName("Fall Back behaviour with No CRT library")
class FallbackBehaviorTests {

@Test
@DisplayName("Should throw error when Sigv4a is ")
void shouldThrowErrorWhenNoFallback() {
Sigv4AauthClient client = Sigv4AauthClient.builder()
.httpClient(mockHttpClient)
.region(Region.US_WEST_2)
.build();

assertThatThrownBy(() -> client.simpleOperationWithNoEndpointParams(r -> r.stringMember("")))
.hasMessageContaining(CRT_DEPENDENCY_ERROR_MESSAGE);
}

}

@Nested
@DisplayName("Region Configuration Tests")
class RegionConfigurationTests {
@Test
@DisplayName("Client Configured Auth Scheme RegionSet take highest precedence ")
void clientConfiguredRegionSetTakesPrecedenceOverEndpointRuleSet() {
environmentVariableHelper.set(SdkSystemSetting.AWS_SIGV4A_SIGNING_REGION_SET, "us-west-2,us-west-1");

CapturingSigner signer = new CapturingSigner();

Sigv4AauthClient sigv4AauthClient = Sigv4AauthClient.builder()
.httpClient(mockHttpClient)
.putAuthScheme(authScheme("aws.auth#sigv4a", signer))
.region(Region.EU_CENTRAL_1)
.build();

Assertions.assertThatThrownBy(() -> sigv4AauthClient.simpleOperationWithEndpointParams(r -> r.stringMember("")))
.hasMessageContaining("stop");

Assertions.assertThat(signer.request.property(AwsV4aHttpSigner.REGION_SET)).isEqualTo(RegionSet.create("us-west-2,"
+ "us-west-1"
));
}

@Test
@DisplayName("Endpoint Rules Auth Scheme RegionSet takes precedence over Endpoint region ")
void endpointRuleSetRegionSetTakesPrecedenceOverEndpointRegion() {

CapturingSigner signer = new CapturingSigner();

Sigv4AauthClient sigv4AauthClient = Sigv4AauthClient.builder()
.httpClient(mockHttpClient)
.putAuthScheme(authScheme("aws.auth#sigv4a", signer))
.region(Region.EU_CENTRAL_1)
.build();

Assertions.assertThatThrownBy(() -> sigv4AauthClient.simpleOperationWithEndpointParams(r -> r.stringMember("")))
.hasMessageContaining("stop");

Assertions.assertThat(signer.request.property(AwsV4aHttpSigner.REGION_SET)).isEqualTo(RegionSet.GLOBAL);
}

@Test
@DisplayName("Endpoint region takes precedence when No RegionSet defined ")
void endpointRegionTakesPrecedenceWhenNoRegionSetFound() {

CapturingSigner signer = new CapturingSigner();

Sigv4AauthClient sigv4AauthClient = Sigv4AauthClient.builder()
.httpClient(mockHttpClient)
.putAuthScheme(authScheme("aws.auth#sigv4a", signer))
.region(Region.EU_CENTRAL_1)
.build();

Assertions.assertThatThrownBy(() -> sigv4AauthClient.simpleOperationWithNoEndpointParams(r -> r.stringMember("")))
.hasMessageContaining("stop");

Assertions.assertThat(signer.request.property(AwsV4aHttpSigner.REGION_SET))
.isEqualTo(RegionSet.create(Region.EU_CENTRAL_1.id()));
}
}


}

0 comments on commit e5fb5b7

Please sign in to comment.