Skip to content

Commit 6b16414

Browse files
authored
GODRIVER-3289 Add option to configure DEK cache lifetime. (#1922)
1 parent 041f700 commit 6b16414

File tree

15 files changed

+709
-9
lines changed

15 files changed

+709
-9
lines changed

internal/integration/json_helpers_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ func createAutoEncryptionOptions(t testing.TB, opts bson.Raw) *options.AutoEncry
162162
aeo.SetEncryptedFieldsMap(encryptedFieldsMap)
163163
case "bypassQueryAnalysis":
164164
aeo.SetBypassQueryAnalysis(opt.Boolean())
165+
case "keyExpirationMS":
166+
aeo.SetKeyExpiration(time.Duration(opt.Int32()) * time.Millisecond)
165167
default:
166168
t.Fatalf("unrecognized auto encryption option: %v", name)
167169
}

internal/integration/unified/client_encryption_operation_execution.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,26 @@ func executeRewrapManyDataKey(ctx context.Context, operation *operation) (*opera
391391
}
392392
return rewrapManyDataKeyResultsOpResult(result)
393393
}
394+
395+
// executeDecrypt will decrypt the given value.
396+
func executeDecrypt(ctx context.Context, operation *operation) (*operationResult, error) {
397+
cee, err := entities(ctx).clientEncryption(operation.Object)
398+
if err != nil {
399+
return nil, err
400+
}
401+
402+
rawValue, err := operation.Arguments.LookupErr("value")
403+
if err != nil {
404+
return nil, err
405+
}
406+
t, d, ok := rawValue.BinaryOK()
407+
if !ok {
408+
return nil, errors.New("'value' argument is not a BSON binary")
409+
}
410+
411+
rawValue, err = cee.Decrypt(ctx, bson.Binary{Subtype: t, Data: d})
412+
if err != nil {
413+
return newErrorResult(err), nil
414+
}
415+
return newValueResult(rawValue.Type, rawValue.Value, err), nil
416+
}

internal/integration/unified/entity.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ type clientEncryptionOpts struct {
179179
KeyVaultClient string `bson:"keyVaultClient"`
180180
KeyVaultNamespace string `bson:"keyVaultNamespace"`
181181
KmsProviders map[string]bson.Raw `bson:"kmsProviders"`
182+
KeyExpirationMS *int64 `bson:"keyExpirationMS"`
182183
}
183184

184185
// EntityMap is used to store entities during tests. This type enforces uniqueness so no two entities can have the same
@@ -735,12 +736,15 @@ func (em *EntityMap) addClientEncryptionEntity(entityOptions *entityOptions) err
735736
return newEntityNotFoundError("client", ceo.KeyVaultClient)
736737
}
737738

738-
ce, err := mongo.NewClientEncryption(
739-
keyVaultClient.Client,
740-
options.ClientEncryption().
741-
SetKeyVaultNamespace(ceo.KeyVaultNamespace).
742-
SetTLSConfig(tlsconf).
743-
SetKmsProviders(kmsProviders))
739+
opts := options.ClientEncryption().
740+
SetKeyVaultNamespace(ceo.KeyVaultNamespace).
741+
SetTLSConfig(tlsconf).
742+
SetKmsProviders(kmsProviders)
743+
if ceo.KeyExpirationMS != nil {
744+
opts.SetKeyExpiration(time.Duration(*ceo.KeyExpirationMS) * time.Millisecond)
745+
}
746+
747+
ce, err := mongo.NewClientEncryption(keyVaultClient.Client, opts)
744748
if err != nil {
745749
return err
746750
}

internal/integration/unified/operation.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat
270270
return executeDeleteKey(ctx, op)
271271
case "addKeyAltName":
272272
return executeAddKeyAltName(ctx, op)
273+
case "decrypt":
274+
return executeDecrypt(ctx, op)
273275

274276
// Unsupported operations
275277
case "count", "listIndexNames":

internal/integration/unified/schema_version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616

1717
var (
1818
supportedSchemaVersions = map[int]string{
19-
1: "1.21",
19+
1: "1.22",
2020
}
2121
)
2222

mongo/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,8 @@ func (c *Client) newMongoCrypt(opts *options.AutoEncryptionOptions) (*mongocrypt
609609
SetEncryptedFieldsMap(cryptEncryptedFieldsMap).
610610
SetCryptSharedLibDisabled(cryptSharedLibDisabled || bypassAutoEncryption).
611611
SetCryptSharedLibOverridePath(cryptSharedLibPath).
612-
SetHTTPClient(opts.HTTPClient))
612+
SetHTTPClient(opts.HTTPClient).
613+
SetKeyExpiration(opts.KeyExpiration))
613614
if err != nil {
614615
return nil, err
615616
}

mongo/client_encryption.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ func NewClientEncryption(keyVaultClient *Client, opts ...options.Lister[options.
5959
// ClientEncryption because it's only needed for AutoEncryption and we don't expect users to
6060
// have the crypt_shared library installed if they're using ClientEncryption.
6161
SetCryptSharedLibDisabled(true).
62-
SetHTTPClient(cea.HTTPClient))
62+
SetHTTPClient(cea.HTTPClient).
63+
SetKeyExpiration(cea.KeyExpiration))
6364
if err != nil {
6465
return nil, err
6566
}

mongo/options/autoencryptionoptions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package options
99
import (
1010
"crypto/tls"
1111
"net/http"
12+
"time"
1213

1314
"go.mongodb.org/mongo-driver/v2/internal/httputil"
1415
)
@@ -40,6 +41,7 @@ type AutoEncryptionOptions struct {
4041
HTTPClient *http.Client
4142
EncryptedFieldsMap map[string]interface{}
4243
BypassQueryAnalysis *bool
44+
KeyExpiration *time.Duration
4345
}
4446

4547
// AutoEncryption creates a new AutoEncryptionOptions configured with default values.
@@ -164,3 +166,11 @@ func (a *AutoEncryptionOptions) SetBypassQueryAnalysis(bypass bool) *AutoEncrypt
164166

165167
return a
166168
}
169+
170+
// SetKeyExpiration specifies duration for the key expiration. 0 or negative value means "never expire".
171+
// The granularity is in milliseconds. Any sub-millisecond fraction will be rounded up.
172+
func (a *AutoEncryptionOptions) SetKeyExpiration(expiration time.Duration) *AutoEncryptionOptions {
173+
a.KeyExpiration = &expiration
174+
175+
return a
176+
}

mongo/options/clientencryptionoptions.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"crypto/tls"
1111
"fmt"
1212
"net/http"
13+
"time"
1314

1415
"go.mongodb.org/mongo-driver/v2/internal/httputil"
1516
)
@@ -22,6 +23,7 @@ type ClientEncryptionOptions struct {
2223
KmsProviders map[string]map[string]interface{}
2324
TLSConfig map[string]*tls.Config
2425
HTTPClient *http.Client
26+
KeyExpiration *time.Duration
2527
}
2628

2729
// ClientEncryptionOptionsBuilder contains options to configure client
@@ -80,6 +82,18 @@ func (c *ClientEncryptionOptionsBuilder) SetTLSConfig(cfg map[string]*tls.Config
8082
return c
8183
}
8284

85+
// SetKeyExpiration specifies duration for the key expiration. 0 or negative value means "never expire".
86+
// The granularity is in milliseconds. Any sub-millisecond fraction will be rounded up.
87+
func (c *ClientEncryptionOptionsBuilder) SetKeyExpiration(expiration time.Duration) *ClientEncryptionOptionsBuilder {
88+
c.Opts = append(c.Opts, func(opts *ClientEncryptionOptions) error {
89+
opts.KeyExpiration = &expiration
90+
91+
return nil
92+
})
93+
94+
return c
95+
}
96+
8397
// BuildTLSConfig specifies tls.Config options for each KMS provider to use to configure TLS on all connections created
8498
// to the KMS provider. The input map should contain a mapping from each KMS provider to a document containing the necessary
8599
// options, as follows:

0 commit comments

Comments
 (0)