Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Threading;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.Runtime.Credentials;

namespace MongoDB.Driver.Authentication.AWS.CredentialsSources
{
Expand All @@ -24,6 +25,7 @@ internal sealed class AWSFallbackCredentialsSource : IAWSCredentialsSource
public static readonly AWSFallbackCredentialsSource Instance = new();

private readonly SemaphoreSlim _lock = new(1);
private Amazon.Runtime.AWSCredentials _cachedCredentialsSource;

public void Dispose() => _lock?.Dispose();

Expand All @@ -33,8 +35,8 @@ public AWSCredentials GetCredentials(CancellationToken cancellationToken)
_lock.Wait(cancellationToken);
try
{
// returns cached credentials source immediately. Only if cached source unavailable, makes quite heavy steps
credentialsSource = FallbackCredentialsFactory.GetCredentials();
// resolving the credentials source walks the full provider chain, so cache it and reuse until reset
credentialsSource = _cachedCredentialsSource ??= DefaultAWSCredentialsIdentityResolver.GetCredentials(null);
Comment thread
adelinowona marked this conversation as resolved.
Outdated
}
finally
{
Expand All @@ -51,8 +53,8 @@ public async Task<AWSCredentials> GetCredentialsAsync(CancellationToken cancella
await _lock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
// returns cached credentials source immediately. Only if cached source unavailable, makes quite heavy steps
credentialsSource = FallbackCredentialsFactory.GetCredentials();
// resolving the credentials source walks the full provider chain, so cache it and reuse until reset
credentialsSource = _cachedCredentialsSource ??= await DefaultAWSCredentialsIdentityResolver.GetCredentialsAsync(null).ConfigureAwait(false);
}
finally
{
Expand All @@ -69,7 +71,7 @@ public void ResetCache()

try
{
FallbackCredentialsFactory.Reset();
_cachedCredentialsSource = null;
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.SecurityToken" Version="3.7.100.14" />
<PackageReference Include="AWSSDK.SecurityToken" Version="4.0.100.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
*/

using System;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using FluentAssertions;
using MongoDB.Bson;
using MongoDB.TestHelpers.XunitExtensions;
Expand Down Expand Up @@ -64,105 +62,5 @@ public void Ecs_should_fill_AWS_CONTAINER_CREDENTIALS_RELATIVE_URI()
var awsContainerUri = Environment.GetEnvironmentVariable("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI") ?? Environment.GetEnvironmentVariable("AWS_CONTAINER_CREDENTIALS_FULL_URI");
Comment on lines 58 to 62

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... I'm not sure we need this test. For a couple of reasons:

  1. We don't have those methods used here anymore. FallbackCredentialsFactory.CredentialsGenerators is obsolete and its closest candidate AWSConfigs.AWSCredentialsGenerators is write only, so we can't read the default handlers
  2. This test was essentially verifying that we get the "expected" chain of handlers to retrieve AWS credentials. Should we worry that the official SDK actually uses our "expected" chain of handlers?
  3. We actually verify that the correct credentials are chosen in our CI matrix with our run-aws-auth-test-with-... tasks.

(awsContainerUri != null).Should().Be(isEcs);
}

@papafe papafe Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the following as an answer to a Copilot comment, but I think it's worth to add it here as well.

So... I'm not sure we need this test. For a couple of reasons:

  1. We don't have those methods used here anymore. FallbackCredentialsFactory.CredentialsGenerators is obsolete and its closest candidate AWSConfigs.AWSCredentialsGenerators is write only, so we can't read the default handlers.
  2. This test was essentially verifying that we get the "expected" chain of handlers to retrieve AWS credentials. Should we worry that the official SDK actually uses our "expected" chain of handlers?
  3. We actually verify that the correct credentials are chosen in our CI matrix with our run-aws-auth-test-with-... tasks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed we were testing third-party library internals so I am supporting dropping the test. Unless there is a very good reason for doing so. @sanych-sun thoughts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sanych-sun Do you agree with removing this test?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with dropping the test as long as there is no our code involved.

[Fact]
public void AwsSdk_should_support_all_required_handlers()
{
var credentialsGeneratorsDelegatesEnumerator = FallbackCredentialsFactory.CredentialsGenerators.GetEnumerator();

// AppConfigAWSCredentials
AWSCredentials credentials = null;
if (Type.GetType("Amazon.Runtime.AppConfigAWSCredentials, AWSSDK.Core", throwOnError: false) != null) // app.config/web.config does not present on windows
{
var appConfigAWSCredentialsException = Record.Exception(() => RunTestCase());
// app.config/web.config case is based on ConfigurationManager. This is not configured for this test
appConfigAWSCredentialsException.Message.Should().Contain("The app.config/web.config files for the application did not contain credential information");
}

// AssumeRoleWithWebIdentityCredentials.FromEnvironmentVariables()
var exception = Record.Exception(() => RunTestCase());
if (Environment.GetEnvironmentVariable("AWS_WEB_IDENTITY_TOKEN_FILE") != null)
{
// aws-web-identity-credentials is configured
exception.Should().BeNull();
credentials.Should().BeOfType<AssumeRoleWithWebIdentityCredentials>();
}
else
{
// otherwise fail
exception.Message.Should().Contain("webIdentityTokenFile");
}

// GetAWSCredentials (Profile)
exception = Record.Exception(() => RunTestCase());
if (IsWithAwsProfileOnMachine())
{
// current machine contains configured aws profile, which may include:
// 1. BasicAWSCredentials (aws_access_key_id and aws_secret_access_key)
// 2. SessionAWSCredentials (aws_access_key_id, aws_secret_access_key, aws_session_token)
exception.Should().BeNull();
credentials.Should().Match(x => x is BasicAWSCredentials || x is SessionAWSCredentials);
}
else
{
// otherwise fail
exception.Message.Should().Contain("Credential").And.Subject.Should().Contain("profile");
}

// EnvironmentVariablesAWSCredentials
exception = Record.Exception(() => RunTestCase());
if (Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID") != null && Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY") != null)
{
// environment variables code path
exception.Should().BeNull();
credentials.Should().BeOfType<EnvironmentVariablesAWSCredentials>();
}
else
{
// otherwise fail
exception.Message.Should().Contain("The environment variables").And.Subject.Contains("were not set with AWS credentials");
}

// ECSEC2CredentialsWrapper
exception = Record.Exception(() => RunTestCase());
if (Environment.GetEnvironmentVariable("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI") != null || Environment.GetEnvironmentVariable("AWS_CONTAINER_CREDENTIALS_FULL_URI") != null)
{
exception.Should().BeNull();
credentials.Should().BeOfType<ECSTaskCredentials>();
}
else
{
exception.Should().BeNull();
credentials.GetType().Name.Should().Contain("DefaultInstanceProfileAWSCredentials"); // EC2 case
}

credentialsGeneratorsDelegatesEnumerator.MoveNext().Should().BeFalse(); // no more handlers

bool IsWithAwsProfileOnMachine()
{
var credentialProfileChain = new CredentialProfileStoreChain();
if (credentialProfileChain.TryGetProfile(Environment.GetEnvironmentVariable("AWS_PROFILE") ?? "default", out var profile))
{
try
{
_ = profile.GetAWSCredentials(credentialProfileChain);
return true;
}
catch
{
return false;
}
}

return false;
}

void RunTestCase()
{
credentials = null;
credentialsGeneratorsDelegatesEnumerator.MoveNext().Should().BeTrue();
credentials = credentialsGeneratorsDelegatesEnumerator.Current();
}
}
}
}