aws / aws-sdk-java-v2

The official AWS SDK for Java - Version 2
Apache License 2.0
2.18k stars 843 forks source link

ProfileFileSupplier.defaultSupplier() leads to NullPointer when config files are missing #5635

Open maschnetwork opened 1 week ago

maschnetwork commented 1 week ago

Describe the bug

We recently introduced automatic credentials reload in the EventBridge Kafka connector by leveraging ProfileFileSupplier.defaultSupplier as recommended in the official docs:

var provider = DefaultCredentialsProvider.builder()
         //.profileFile(ProfileFile.defaultProfileFile()) <- this is the default by the SDK 
          .profileFile(ProfileFileSupplier.defaultSupplier()) //<- This supports automatic reload
          .build();

var creds = provider.resolveCredentials();

However, when no credential files are present (~/.aws/credentials and ~/.aws/config are missing) the DefaultCredentialProviderChain.resolveCredentials() process will result in NullPointer Exceptions in both ProfileCredentialsProvider and InstanceProfileCredentialProvider: java.lang.NullPointerException: Cannot invoke "java.nio.file.Path.getFileSystem()" because "path" is null. (See Additional Information below).

This will happen first in the ProfileCredentialsProvider and will be ignored to move to the next provider as outlined here. But the process will run into it again for the InstanceProfileCredentialProvider, for example in Ec2MetaDataConfigProvider.

This behavior essentially influences (and breaks) the DefaultCredentialsProvider chain. It behaves differently than the current SDK default value ProfileFile.defaultProfileFile() which does not produce any exceptions and lets InstanceProfileCredentialProvider resolve even though files are missing.

Related issues:

https://github.com/awslabs/eventbridge-kafka-connector/issues/396

Expected Behavior

ProfileFileSupplier.defaultSupplier() behaves the same as ProfileFile.defaultProfileFile() when credential files are missing.

Current Behavior

ProfileFileSupplier.defaultSupplier() leads to Nullpointer during resolution process and breaks DefaultCredentialsProvider (or at least behaves different than the default)

Reproduction Steps

  1. First, delete local files such as ~/.aws/credentials and ~/.aws/config
  2. Run the below code with the default value of ProfileFile.defaultProfileFile()
  3. Run the below code with the non-default value: profileFile(ProfileFileSupplier.defaultSupplier()
public class Main {
    public static void main(String[] args) {
        var provider = DefaultCredentialsProvider.builder()
                    //    .profileFile(ProfileFile.defaultProfileFile()) <- This is the default and is used implicit
                        .profileFile(ProfileFileSupplier.defaultSupplier()) // <- This produces NullPointer when no credentials files are present (Check Errors in the ProviderChain) 
                        .build();

        var creds = provider.resolveCredentials();
        System.out.println(creds);
    }
}
  1. Check for Nullpointer in the resolution process and see different path for InstanceProfileCredentialsProvider

Possible Solution

When no credential files are present (~/.aws/credentials and ~/.aws/config. are missing) ProfileFileSupplier.defaultSupplier() effectively returns ProfileFile.builder().build()since credentialsSupplierOptional and configurationSupplierOptional are empty. Later during resolveCredentials of the DefaultCredentialsProviderChain the contentLocation within ProfileFile Builder will be null and therefore lead to the Nullpointer:

@Override
public ProfileFile build() {
    InputStream stream = content != null ? content :
                         FunctionalUtils.invokeSafely(() -> Files.newInputStream(contentLocation));

It would make sense to provide a sane default here such as ProfileFile.defaultProfileFile().

Additional Information/Context

This will happen first in the ProfileCredentialsProvider and will be ignored to move to the next provider as outlined here. But InstanceProfileCredentialProvider will run into it again, for example in Ec2MetaDataConfigProvider.

AWS Java SDK version used

2.28.8

JDK version used

17

Operating System and version

MacOS

debora-ito commented 3 days ago

Acknowledged. We should fix the NullPointerException.