-
Notifications
You must be signed in to change notification settings - Fork 933
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?
Changes from 10 commits
a95c313
4f70639
11b407d
28a624d
dba982e
1ece12e
875316d
38501d3
ec2df09
46417a2
0eff704
5f28ab0
26c055d
6b68995
a61c360
1f34369
81cc95d
38e7d0b
7bede64
eb9de76
5214e64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||
| // Copyright (C) MongoDB, Inc. 2017-present. | ||||||
| // | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||||
| // not use this file except in compliance with the License. You may obtain | ||||||
| // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|
|
||||||
| // This package allows credential providers and signers in v2 AWS SDK to be | ||||||
| // supplied to the MongoDB Go Driver for use with the MONGODB-AWS authentication | ||||||
| // mechanism. | ||||||
| // | ||||||
| // NewCredentialsProvider() adapts an AWS CredentialsProvider to be used in: | ||||||
| // | ||||||
| // ClientOptions | ||||||
| // ClinetEncryptionOptions | ||||||
|
||||||
| // ClinetEncryptionOptions | |
| // ClientEncryptionOptions |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,21 @@ | ||||||
| module go.mongodb.org/mongo-driver/v2/awsauth | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're planning to tag the initial module release with
Suggested change
|
||||||
|
|
||||||
| go 1.23 | ||||||
|
|
||||||
| require ( | ||||||
| github.com/aws/aws-sdk-go-v2 v1.40.1 | ||||||
| go.mongodb.org/mongo-driver/v2 v2.0.0-beta2 | ||||||
| ) | ||||||
|
|
||||||
| require ( | ||||||
| github.com/aws/smithy-go v1.24.0 // indirect | ||||||
| github.com/golang/snappy v1.0.0 // indirect | ||||||
| github.com/klauspost/compress v1.17.6 // indirect | ||||||
| github.com/xdg-go/pbkdf2 v1.0.0 // indirect | ||||||
| github.com/xdg-go/scram v1.2.0 // indirect | ||||||
| github.com/xdg-go/stringprep v1.0.4 // indirect | ||||||
| github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect | ||||||
| golang.org/x/crypto v0.33.0 // indirect | ||||||
| golang.org/x/sync v0.11.0 // indirect | ||||||
| golang.org/x/text v0.22.0 // indirect | ||||||
| ) | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| github.com/aws/aws-sdk-go-v2 v1.40.1 h1:difXb4maDZkRH0x//Qkwcfpdg1XQVXEAEs2DdXldFFc= | ||
| github.com/aws/aws-sdk-go-v2 v1.40.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= | ||
| github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= | ||
| github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= | ||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= | ||
| github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | ||
| github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||
| github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
| github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= | ||
| github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= | ||
| github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= | ||
| github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= | ||
| github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs= | ||
| github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8= | ||
| github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= | ||
| github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= | ||
| github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= | ||
| github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= | ||
| github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | ||
| go.mongodb.org/mongo-driver/v2 v2.0.0-beta2 h1:PRtbRKwblE8ZfI8qOhofcjn9y8CmKZI7trS5vDMeJX0= | ||
| go.mongodb.org/mongo-driver/v2 v2.0.0-beta2/go.mod h1:UGLb3ZgEzaY0cCbJpH9UFt9B6gEXiTPzsnJS38nBeoU= | ||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
| golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||
| golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= | ||
| golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= | ||
| golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||
| golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||
| golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
| golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
| golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= | ||
| golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
| golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
| golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
| golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
| golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= | ||
| golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= | ||
| golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= | ||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
| golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optional: Rename file to |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| // Copyright (C) MongoDB, Inc. 2017-present. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
| // not use this file except in compliance with the License. You may obtain | ||
| // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| package awsauth | ||
|
|
||
| import ( | ||
| "context" | ||
| "crypto/sha256" | ||
| "encoding/hex" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/aws/aws-sdk-go-v2/aws" | ||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | ||
|
|
||
| "go.mongodb.org/mongo-driver/v2/mongo/options" | ||
| ) | ||
|
|
||
| const ( | ||
| // emptyStringSHA256 is a SHA256 of an empty string | ||
| emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` | ||
| ) | ||
|
|
||
| var _ options.AWSCredentialsProvider = (*CredentialsProvider)(nil) | ||
|
|
||
| // CredentialsProvider is an implementation of options.AWSCredentialsProvider in | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] This documentation is kind of missleading. CredentialsProvider is just a thin wrapper around aws.CredentialsProvider and doesn't directly provide "caching and concurrency safe credentials retrieval". // CredentialsProvider adapts an AWS SDK v2 CredentialsProvider to the
// options.AWSCredentialsProvider interface used by the MongoDB Go Driver. |
||
| // MongoDB Go driver. It provides caching and concurrency safe credentials retrieval | ||
| // via the provider's retrieve method. | ||
| type CredentialsProvider struct { | ||
|
prestonvasquez marked this conversation as resolved.
Outdated
|
||
| provider aws.CredentialsProvider | ||
| } | ||
|
|
||
| // NewCredentialsProvider returns a CredentialsProvider that wraps AWS | ||
| // CredentialsProvider. Provider is expected to not be nil. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
[question] Should we just validate this to prevent misuse? |
||
| func NewCredentialsProvider(provider aws.CredentialsProvider) *CredentialsProvider { | ||
| return &CredentialsProvider{ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [question] Does this need to return a pointer references? Whatever we decide, can we make
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making the |
||
| provider: provider, | ||
| } | ||
| } | ||
|
|
||
| // Retrieve returns the credentials. | ||
| func (p *CredentialsProvider) Retrieve(ctx context.Context) (options.AWSCredentials, error) { | ||
| creds, err := p.provider.Retrieve(ctx) | ||
| return options.AWSCredentials(creds), err | ||
| } | ||
|
|
||
| var _ options.AWSSigner = (*Signer)(nil) | ||
|
|
||
| // Signer is an implementation of options.AWSSigner in MongoDB Go driver. | ||
| type Signer struct { | ||
| signer v4.HTTPSigner | ||
| } | ||
|
|
||
| // NewSigner creates a new Signer from the provided AWS HTTPSigner. | ||
| func NewSigner(httpSigner v4.HTTPSigner) Signer { | ||
| return Signer{ | ||
| signer: httpSigner, | ||
| } | ||
| } | ||
|
|
||
| // Sign signs AWS v4 requests. | ||
| func (s Signer) Sign( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [docs] We should note that this method hashes the payload if it's not empty. |
||
| ctx context.Context, creds options.AWSCredentials, r *http.Request, | ||
| payload, service, region string, signingTime time.Time) error { | ||
| if len(payload) == 0 { | ||
| payload = emptyStringSHA256 | ||
| } else { | ||
| hash := sha256.Sum256([]byte(payload)) | ||
| payload = hex.EncodeToString(hash[:]) | ||
| } | ||
| r.Header.Set("X-Amz-Security-Token", creds.SessionToken) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [question] Do we need to guard this against empty
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guard is in aws_conv.go. IMO, the methods in this file should only be a shin layer that adapts the AWS SDK to the go driver interface. Therefore, we shouldn't include a lot of go driver logic here.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICT we don't unset |
||
| return s.signer.SignHTTP(ctx, aws.Credentials(creds), r, payload, service, region, signingTime) | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,45 @@ | ||||||
| // Copyright (C) MongoDB, Inc. 2017-present. | ||||||
| // | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||||
| // not use this file except in compliance with the License. You may obtain | ||||||
| // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|
|
||||||
| package awsauth | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Testable examples should always be in a
Suggested change
|
||||||
|
|
||||||
| import ( | ||||||
| "github.com/aws/aws-sdk-go-v2/aws" | ||||||
| v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" | ||||||
| "go.mongodb.org/mongo-driver/v2/mongo" | ||||||
| "go.mongodb.org/mongo-driver/v2/mongo/options" | ||||||
| ) | ||||||
|
|
||||||
| func ExampleNewCredentialsProvider() { | ||||||
| awsCredentialProvider := NewCredentialsProvider(aws.NewConfig().Credentials) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [docs] Users would typically load credentials using cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
panic(err)
}
awsCredentialProvider := NewCredentialsProvider(cfg.Credentials) |
||||||
| credential := options.Credential{ | ||||||
| AuthMechanism: "MONGODB-AWS", | ||||||
| AWSCredentialsProvider: awsCredentialProvider, | ||||||
| } | ||||||
| client, err := mongo.Connect( | ||||||
| options.Client().SetAuth(credential)) | ||||||
| if err != nil { | ||||||
| panic(err) | ||||||
| } | ||||||
| _ = client | ||||||
| } | ||||||
|
|
||||||
| func ExampleNewSigner() { | ||||||
| awsCredentialProvider := NewCredentialsProvider(aws.NewConfig().Credentials) | ||||||
| awsSigner := NewSigner(v4.NewSigner()) | ||||||
| _ = awsSigner | ||||||
| credential := options.Credential{ | ||||||
| AuthMechanism: "MONGODB-AWS", | ||||||
| AWSCredentialsProvider: awsCredentialProvider, | ||||||
| AWSSigner: awsSigner, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned asking customers to specify both We should either:
I prefer option 2 because it seems to be a better overall customer experience. While it would be nice to eventually remove the AWS v4 signing logic from the Go Driver, it doesn't seem worth a more confusing API. |
||||||
| } | ||||||
| client, err := mongo.Connect( | ||||||
| options.Client().SetAuth(credential)) | ||||||
| if err != nil { | ||||||
| panic(err) | ||||||
| } | ||||||
| _ = client | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,4 +9,5 @@ use ( | |
| ./internal/cmd/faas/awslambda/mongodb | ||
| ./internal/test/compilecheck | ||
| ./internal/test/goleak | ||
| ./ext/awsauth | ||
| ) | ||
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.
[docs] We should add context about avoiding the AWS SDK depenency in the main driver: