amazon-s3-encryption-client-java icon indicating copy to clipboard operation
amazon-s3-encryption-client-java copied to clipboard

Region is not propagated when using the KMS client

Open NathanEckert opened this issue 1 year ago • 0 comments

Problem:

The following code fails (if the credential chain does not provide the region):

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
import org.junitpioneer.jupiter.ClearEnvironmentVariable;
import org.junitpioneer.jupiter.ClearSystemProperty;
import org.junitpioneer.jupiter.SetEnvironmentVariable;
import org.junitpioneer.jupiter.SetSystemProperty;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.encryption.s3.S3EncryptionClient;


@Isolated
@ClearEnvironmentVariable(key = SdkConstants.EnvironmentVariables.AWS_REGION)
@ClearSystemProperty(key = SdkConstants.SystemProperties.AWS_REGION)
@SetSystemProperty(key = SdkConstants.SystemProperties.AWS_EC2_METADATA_DISABLED, value = "true")
@SetEnvironmentVariable(
    key = SdkConstants.EnvironmentVariables.AWS_EC2_METADATA_DISABLED,
    value = "true")
public class TestClientSideEncryption {
  private static final Region REGION = Region.EU_WEST_3;

  @BeforeEach
  void ensureRegionIsNotSet() {
    // We check all the ways the SDK is capable of loading the region when resolving the credentials
    // chain.
    assertThat(System.getProperty(SdkConstants.SystemProperties.AWS_REGION)).isNull();
    assertThat(System.getenv(SdkConstants.EnvironmentVariables.AWS_REGION)).isNull();
    assertThat(System.getProperty(SdkConstants.SystemProperties.AWS_EC2_METADATA_DISABLED))
        .isEqualTo("true");
    assertThat(System.getenv(SdkConstants.EnvironmentVariables.AWS_EC2_METADATA_DISABLED))
        .isEqualTo("true");
  }

  @Test
  void testBuildEncryptionClientWithKms() {
    final S3Client client = S3Client.builder()
        .credentialsProvider(DefaultCredentialsProvider.create())
        .region(REGION)
        .build();
    final S3AsyncClient asyncClient = S3AsyncClient.builder()
        .credentialsProvider(DefaultCredentialsProvider.create())
        .region(REGION)
        .build();

    S3EncryptionClient.builder()
        .kmsKeyId(S3_KMS_KEY)
        .wrappedClient(client)
        .wrappedAsyncClient(asyncClient)
        .build();
  }
}

with the following stacktrace:

software.amazon.awssdk.core.exception.SdkClientException: Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@cb03411: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@455824ad: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@3be4fcc0: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@431f1eaf: Unable to contact EC2 metadata service.]

	at software.amazon.awssdk.core.exception.SdkClientException$BuilderImpl.build(SdkClientException.java:111)
	at software.amazon.awssdk.regions.providers.AwsRegionProviderChain.getRegion(AwsRegionProviderChain.java:70)
	at software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder.resolveRegion(AwsDefaultClientBuilder.java:296)
	at software.amazon.awssdk.utils.AttributeMap$DerivedValue.primeCache(AttributeMap.java:600)
	at software.amazon.awssdk.utils.AttributeMap$DerivedValue.get(AttributeMap.java:589)
	at software.amazon.awssdk.utils.AttributeMap$Builder.resolveValue(AttributeMap.java:396)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at software.amazon.awssdk.utils.AttributeMap$Builder.build(AttributeMap.java:362)
	at software.amazon.awssdk.core.client.config.SdkClientConfiguration$Builder.build(SdkClientConfiguration.java:232)
	at software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder.finalizeAwsConfiguration(AwsDefaultClientBuilder.java:187)
	at software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder.finalizeChildConfiguration(AwsDefaultClientBuilder.java:163)
	at software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder.syncClientConfiguration(SdkDefaultClientBuilder.java:194)
	at software.amazon.awssdk.services.kms.DefaultKmsClientBuilder.buildClient(DefaultKmsClientBuilder.java:36)
	at software.amazon.awssdk.services.kms.DefaultKmsClientBuilder.buildClient(DefaultKmsClientBuilder.java:25)
	at software.amazon.awssdk.core.client.builder.SdkDefaultClientBuilder.build(SdkDefaultClientBuilder.java:161)
	at software.amazon.awssdk.services.kms.KmsClient.create(KmsClient.java:19586)
	at software.amazon.encryption.s3.materials.KmsKeyring$Builder.build(KmsKeyring.java:262)
	at software.amazon.encryption.s3.S3EncryptionClient$Builder.build(S3EncryptionClient.java:803)
	at io.atoti.loading.s3.private_.TestClientSideEncryption.testBuildEncryptionClientWithKms(TestClientSideEncryption.java:50)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)

This seems to be the same problem as #183 which is supposed to be fixed (I use version 3.1.3 and it is supposed to be fixed since 3.1.2)

It seems that the KMS client does not pass along correctly the region, which is then resolved through the credential chain.

It is interesting to note that this issue does not exist with a rsa KeyPair

NathanEckert avatar Jun 20 '24 15:06 NathanEckert