Skip to content

Conversation

@qingyang-hu
Copy link
Collaborator

GODRIVER-3454
GODRIVER-3615

Summary

Support custom AWS credential provider.

Background & Motivation

@mongodb-drivers-pr-bot
Copy link
Contributor

mongodb-drivers-pr-bot bot commented Oct 25, 2025

🧪 Performance Results

Commit SHA: f64ee4a

The following benchmark tests for version 68ffc1031d36eb0007ce6e23 had statistically significant changes (i.e., |z-score| > 1.96):

Benchmark Measurement % Change Patch Value Stable Region H-Score Z-Score
BenchmarkBSONDeepDocumentDecoding ops_per_second_min -41.7251 1165.8205 Avg: 2000.5549
Med: 2006.1911
Stdev: 169.4871
0.8997 -4.9251
BenchmarkBSONFullDocumentDecoding ops_per_second_min -22.9590 1520.8270 Avg: 1974.0480
Med: 1972.0054
Stdev: 137.6046
0.8321 -3.2936
BenchmarkSingleRunCommand ops_per_second_med -15.4758 6518.1825 Avg: 7711.6212
Med: 7754.0117
Stdev: 369.9259
0.8437 -3.2262
BenchmarkSingleRunCommand total_mem_allocs -13.8956 912833.0000 Avg: 1060147.0750
Med: 1073742.5000
Stdev: 62373.9734
0.7911 -2.3618
BenchmarkSingleRunCommand total_bytes_allocated -13.5777 84838440.0000 Avg: 98167319.2000
Med: 99483612.0000
Stdev: 5850626.2752
0.7848 -2.2782
BenchmarkSingleFindOneByID total_mem_allocs -13.1278 1439775.0000 Avg: 1657347.7045
Med: 1669065.0000
Stdev: 80665.9833
0.8018 -2.6972
BenchmarkMultiInsertSmallDocument total_mem_allocs 13.0977 2563534.0000 Avg: 2266653.7727
Med: 2237305.0000
Stdev: 118196.3477
0.8053 2.5118
BenchmarkSingleFindOneByID total_bytes_allocated -12.3774 89741224.0000 Avg: 102417896.1818
Med: 103078548.0000
Stdev: 4957598.8142
0.7897 -2.5570
BenchmarkSingleRunCommand ops_per_second_max -12.1895 7606.7030 Avg: 8662.6348
Med: 8693.0820
Stdev: 264.2075
0.8775 -3.9966
BenchmarkMultiInsertSmallDocument total_time_seconds 11.4729 1.1829 Avg: 1.0612
Med: 1.0471
Stdev: 0.0460
0.8170 2.6438
BenchmarkMultiInsertSmallDocument total_bytes_allocated 9.6552 489449776.0000 Avg: 446353345.6552
Med: 445057428.0000
Stdev: 14534574.7156
0.8241 2.9651
BenchmarkSmallDocInsertOne ops_per_second_max -8.5688 5699.8894 Avg: 6234.0744
Med: 6237.7584
Stdev: 171.9235
0.8374 -3.1071
BenchmarkSingleFindOneByID total_time_seconds -8.5502 1.0507 Avg: 1.1489
Med: 1.1566
Stdev: 0.0483
0.7305 -2.0323
BenchmarkBSONDeepDocumentEncoding total_mem_allocs -6.6786 231348.0000 Avg: 247904.6667
Med: 246617.5000
Stdev: 8118.0178
0.7519 -2.0395
BenchmarkBSONDeepDocumentEncoding total_bytes_allocated -6.5590 164938952.0000 Avg: 176516768.0000
Med: 175614804.0000
Stdev: 5673356.3806
0.7522 -2.0407
BenchmarkSingleFindOneByID ops_per_second_med -6.5014 3891.8153 Avg: 4162.4297
Med: 4188.7448
Stdev: 122.3568
0.7651 -2.2117
BenchmarkSingleFindOneByID ns_per_op 6.4482 262670.0000 Avg: 246758.5882
Med: 244841.0000
Stdev: 7789.6205
0.7423 2.0426
BenchmarkSmallDocInsertOne total_time_seconds 4.8220 1.2412 Avg: 1.1841
Med: 1.1847
Stdev: 0.0236
0.7838 2.4172
BenchmarkBSONDeepDocumentDecoding ops_per_second_max 3.3125 17830.3973 Avg: 17258.6987
Med: 17200.7500
Stdev: 201.4995
0.8510 2.8372
BenchmarkBSONDeepDocumentDecoding ops_per_second_med 2.7233 17148.8347 Avg: 16694.2022
Med: 16711.9281
Stdev: 231.3733
0.7801 1.9649
BenchmarkBSONDeepDocumentEncoding total_time_seconds -1.5379 1.1766 Avg: 1.1949
Med: 1.1946
Stdev: 0.0074
0.7802 -2.4914
BenchmarkLargeDocInsertOne allocated_bytes_per_op -0.7268 5646.0000 Avg: 5687.3333
Med: 5687.0000
Stdev: 2.5166
0.9731 -16.4242
BenchmarkSmallDocInsertOne allocated_bytes_per_op -0.4454 5662.0000 Avg: 5687.3333
Med: 5688.0000
Stdev: 3.0551
0.9474 -8.2923
BenchmarkBSONDeepDocumentEncoding allocated_bytes_per_op 0.1245 2145.0000 Avg: 2142.3333
Med: 2142.5000
Stdev: 1.2111
0.7708 2.2019

For a comprehensive view of all microbenchmark results for this PR's commit, please check out the Evergreen perf task for this patch.

@mongodb-drivers-pr-bot
Copy link
Contributor

mongodb-drivers-pr-bot bot commented Oct 25, 2025

API Change Report

./v2/mongo/options

compatible changes

(*AutoEncryptionOptions).SetCredentialProviders: added
(*ClientEncryptionOptionsBuilder).SetCredentialProviders: added
AutoEncryptionOptions.CredentialProviders: added
ClientEncryptionOptions.CredentialProviders: added
Credential.AwsCredentialsProvider: added
Credentials: added
CredentialsProvider: added

./v2/x/mongo/driver

compatible changes

Cred.AwsCredentialsProvider: added

./v2/x/mongo/driver/auth

incompatible changes

MongoDBAWSAuthenticator: old is comparable, new is not

./v2/x/mongo/driver/mongocrypt/options

compatible changes

(*MongoCryptOptions).SetCredentialProviders: added
MongoCryptOptions.CredentialProviders: added

@qingyang-hu qingyang-hu force-pushed the godriver3615 branch 11 times, most recently from 117f461 to a1b8f64 Compare October 27, 2025 15:42
})
}

func TestCustomAwsCredentialsProse(t *testing.T) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Put this aside from TestClientSideEncryptionProse so Setenv() can be used without being influenced by t.Parallel().

@qingyang-hu qingyang-hu marked this pull request as ready for review October 27, 2025 18:30
@qingyang-hu qingyang-hu requested a review from a team as a code owner October 27, 2025 18:30
@qingyang-hu qingyang-hu requested review from Copilot, matthewdale and prestonvasquez and removed request for prestonvasquez October 27, 2025 18:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for custom AWS credential providers, enabling applications to supply their own AWS credential retrieval logic for both authentication and client-side encryption. The implementation allows users to provide custom credential providers as a callback function that returns AWS credentials on demand.

Key changes:

  • Added AwsCredentialsProvider callback field to credential options for connection authentication
  • Extended client-side encryption options to support custom credential providers via CredentialProviders map
  • Refactored internal credential provider interface to use context-aware Retrieve(context.Context) method consistently across all provider implementations

Reviewed Changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
mongo/options/clientoptions.go Added AwsCredentialsProvider field and Credentials type to support custom AWS credential callbacks
mongo/options/clientencryptionoptions.go Added CredentialProviders map and setter for custom provider configuration
mongo/options/autoencryptionoptions.go Added CredentialProviders field and setter for auto-encryption provider configuration
x/mongo/driver/topology/topology_options.go Converted user-provided credential provider to internal format during credential conversion
x/mongo/driver/driver.go Added AwsCredentialsProvider field to Cred struct for internal provider storage
x/mongo/driver/auth/mongodbaws.go Integrated custom credential provider into AWS authentication flow
x/mongo/driver/mongocrypt/options/mongocrypt_options.go Added CredentialProviders field to MongoCrypt options
x/mongo/driver/mongocrypt/mongocrypt.go Wired custom credential providers into MongoCrypt initialization
mongo/client.go Converted credential providers for auto-encryption setup
mongo/client_encryption.go Converted credential providers for client encryption setup
internal/credproviders/aws_provider.go New provider implementation that wraps custom AWS credential callbacks
internal/aws/types.go Added public Credentials type for custom provider return values
internal/aws/credentials/credentials.go Unified provider interface to use context-aware Retrieve(context.Context) method
internal/credproviders/*.go Updated all provider implementations to use context-aware retrieval
x/mongo/driver/auth/mongodbaws_test.go Added tests for custom credential provider behavior
internal/integration/client_side_encryption_prose_test.go Added integration tests for custom credential provider scenarios
mongo/client_examples_test.go Added example demonstrating custom credential provider usage

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +43 to +45
if a.credentials == nil || a.credentials.ExpirationCallback == nil {
return true
}
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

The IsExpired logic returns true when credentials are nil, which means the provider will always be considered expired before the first retrieval. This forces an immediate retrieval, but if ExpirationCallback is also nil after the first retrieval, it will always return true, causing credentials to be re-fetched on every call. Consider returning a.credentials == nil when ExpirationCallback is nil to avoid unnecessary re-fetching after initial retrieval.

Suggested change
if a.credentials == nil || a.credentials.ExpirationCallback == nil {
return true
}
if a.credentials == nil {
return true
}
if a.credentials.ExpirationCallback == nil {
return false
}

Copilot uses AI. Check for mistakes.
Comment on lines 604 to 617
providers[k] = &credproviders.AwsProvider{
Provider: func(ctx context.Context) (aws.Credentials, error) {
var creds aws.Credentials
c, err := fn(ctx)
if err != nil {
return creds, err
}
creds.AccessKeyID = c.AccessKeyID
creds.SecretAccessKey = c.SecretAccessKey
creds.SessionToken = c.SessionToken
creds.ExpirationCallback = c.ExpirationCallback
return creds, nil
},
}
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

The closure over fn in the loop may capture the wrong value if the loop variable is reused. While this loop only processes the 'aws' key specifically, consider using a function parameter or declaring fn within the block to ensure correct closure capture: provider := fn before the closure.

Copilot uses AI. Check for mistakes.
Comment on lines 62 to 75
providers[k] = &credproviders.AwsProvider{
Provider: func(ctx context.Context) (aws.Credentials, error) {
var creds aws.Credentials
c, err := fn(ctx)
if err != nil {
return creds, err
}
creds.AccessKeyID = c.AccessKeyID
creds.SecretAccessKey = c.SecretAccessKey
creds.SessionToken = c.SessionToken
creds.ExpirationCallback = c.ExpirationCallback
return creds, nil
},
}
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

The closure over fn in the loop may capture the wrong value if the loop variable is reused. While this loop only processes the 'aws' key specifically, consider using a function parameter or declaring fn within the block to ensure correct closure capture: provider := fn before the closure.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants