- 
                Notifications
    You must be signed in to change notification settings 
- Fork 918
GODRIVER-3454 Support custom AWS credential provider. #2228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| 🧪 Performance ResultsCommit SHA: 4fea597The following benchmark tests for version 6903c480cb08c400079f4a12 had statistically significant changes (i.e., |z-score| > 1.96): 
 For a comprehensive view of all microbenchmark results for this PR's commit, please check out the Evergreen perf task for this patch. | 
| API Change Report./v2/mongo/optionscompatible changes(*AutoEncryptionOptions).SetCredentialProviders: added ./v2/x/mongo/drivercompatible changesCred.AwsCredentialsProvider: added ./v2/x/mongo/driver/authincompatible changesMongoDBAWSAuthenticator: old is comparable, new is not ./v2/x/mongo/driver/mongocrypt/optionscompatible changes(*MongoCryptOptions).SetCredentialProviders: added | 
117f461    to
    a1b8f64      
    Compare
  
    a1b8f64    to
    795b157      
    Compare
  
    | }) | ||
| } | ||
|  | ||
| func TestCustomAwsCredentialsProse(t *testing.T) { | 
There was a problem hiding this comment.
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().
There was a problem hiding this 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 AwsCredentialsProvidercallback field to credential options for connection authentication
- Extended client-side encryption options to support custom credential providers via CredentialProvidersmap
- 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 AwsCredentialsProviderfield andCredentialstype to support custom AWS credential callbacks | 
| mongo/options/clientencryptionoptions.go | Added CredentialProvidersmap and setter for custom provider configuration | 
| mongo/options/autoencryptionoptions.go | Added CredentialProvidersfield 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 AwsCredentialsProviderfield toCredstruct 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 CredentialProvidersfield 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 Credentialstype 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.
| if a.credentials == nil || a.credentials.ExpirationCallback == nil { | ||
| return true | ||
| } | 
    
      
    
      Copilot
AI
    
    
    
      Oct 27, 2025 
    
  
There was a problem hiding this comment.
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.
| if a.credentials == nil || a.credentials.ExpirationCallback == nil { | |
| return true | |
| } | |
| if a.credentials == nil { | |
| return true | |
| } | |
| if a.credentials.ExpirationCallback == nil { | |
| return false | |
| } | 
| 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 | ||
| }, | ||
| } | 
    
      
    
      Copilot
AI
    
    
    
      Oct 27, 2025 
    
  
There was a problem hiding this comment.
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.
| 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 | ||
| }, | ||
| } | 
    
      
    
      Copilot
AI
    
    
    
      Oct 27, 2025 
    
  
There was a problem hiding this comment.
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.
f64ee4a    to
    1a5bc81      
    Compare
  
    1a5bc81    to
    4fea597      
    Compare
  
    
GODRIVER-3454
GODRIVER-3615
Summary
Support custom AWS credential provider.
Background & Motivation