31
31
#include "mongoc/mongoc-client-side-encryption-private.h"
32
32
33
33
#include "mongoc/mongoc-uri.h"
34
+ #include "mongoc/mongoc-http-private.h"
34
35
35
36
static void
36
37
_before_test (json_test_ctx_t * ctx , const bson_t * test )
@@ -2596,7 +2597,7 @@ test_kms_tls_cert_wrong_host (void *unused)
2596
2597
mongoc_client_destroy (client );
2597
2598
}
2598
2599
2599
- typedef enum { NO_CLIENT_CERT , WITH_TLS , INVALID_HOSTNAME , EXPIRED , WITH_NAMES } tls_test_ce_t ;
2600
+ typedef enum { NO_CLIENT_CERT , WITH_TLS , INVALID_HOSTNAME , EXPIRED , WITH_NAMES , RETRY } tls_test_ce_t ;
2600
2601
2601
2602
static mongoc_client_encryption_t *
2602
2603
_tls_test_make_client_encryption (mongoc_client_t * keyvault_client , tls_test_ce_t test_ce )
@@ -2619,7 +2620,9 @@ _tls_test_make_client_encryption (mongoc_client_t *keyvault_client, tls_test_ce_
2619
2620
char * ca_file = test_framework_getenv_required ("MONGOC_TEST_CSFLE_TLS_CA_FILE" );
2620
2621
char * certificate_key_file = test_framework_getenv_required ("MONGOC_TEST_CSFLE_TLS_CERTIFICATE_KEY_FILE" );
2621
2622
2622
- if (test_ce == WITH_TLS ) {
2623
+ if (test_ce == WITH_TLS || test_ce == RETRY ) {
2624
+ const char * port = test_ce == RETRY ? "9003" : "9002" ;
2625
+
2623
2626
kms_providers = tmp_bson ("{'aws': {'accessKeyId': '%s', 'secretAccessKey': '%s' }}" ,
2624
2627
mongoc_test_aws_access_key_id ,
2625
2628
mongoc_test_aws_secret_access_key );
@@ -2629,19 +2632,21 @@ _tls_test_make_client_encryption (mongoc_client_t *keyvault_client, tls_test_ce_
2629
2632
bson_concat (kms_providers ,
2630
2633
tmp_bson ("{'azure': {'tenantId': '%s', 'clientId': '%s', "
2631
2634
"'clientSecret': '%s', "
2632
- "'identityPlatformEndpoint': '127.0.0.1:9002 ' }}" ,
2635
+ "'identityPlatformEndpoint': '127.0.0.1:%s ' }}" ,
2633
2636
mongoc_test_azure_tenant_id ,
2634
2637
mongoc_test_azure_client_id ,
2635
- mongoc_test_azure_client_secret ));
2638
+ mongoc_test_azure_client_secret ,
2639
+ port ));
2636
2640
bson_concat (
2637
2641
tls_opts ,
2638
2642
tmp_bson ("{'azure': {'tlsCaFile': '%s', 'tlsCertificateKeyFile': '%s' }}" , ca_file , certificate_key_file ));
2639
2643
2640
2644
bson_concat (kms_providers ,
2641
2645
tmp_bson ("{'gcp': { 'email': '%s', 'privateKey': '%s', "
2642
- "'endpoint': '127.0.0.1:9002 ' }}" ,
2646
+ "'endpoint': '127.0.0.1:%s ' }}" ,
2643
2647
mongoc_test_gcp_email ,
2644
- mongoc_test_gcp_privatekey ));
2648
+ mongoc_test_gcp_privatekey ,
2649
+ port ));
2645
2650
bson_concat (
2646
2651
tls_opts ,
2647
2652
tmp_bson ("{'gcp': {'tlsCaFile': '%s', 'tlsCertificateKeyFile': '%s' }}" , ca_file , certificate_key_file ));
@@ -3228,6 +3233,60 @@ test_kms_tls_options_extra_rejected (void *unused)
3228
3233
mongoc_client_destroy (keyvault_client );
3229
3234
}
3230
3235
3236
+ static const char * failpoint_server_ip = "127.0.0.1" ;
3237
+ static const int failpoint_server_port = 9003 ;
3238
+
3239
+ static void
3240
+ reset_failpoints (mongoc_ssl_opt_t * ssl_opts )
3241
+ {
3242
+ mongoc_http_request_t req ;
3243
+ mongoc_http_response_t res ;
3244
+ bool r ;
3245
+ bson_error_t error = {0 };
3246
+
3247
+ _mongoc_http_request_init (& req );
3248
+ _mongoc_http_response_init (& res );
3249
+
3250
+ req .method = "POST" ;
3251
+ req .host = failpoint_server_ip ;
3252
+ req .port = failpoint_server_port ;
3253
+ req .path = "/reset" ;
3254
+
3255
+ r = _mongoc_http_send (& req , 10000 , true, ssl_opts , & res , & error );
3256
+ ASSERT_OR_PRINT (r , error );
3257
+ _mongoc_http_response_cleanup (& res );
3258
+ }
3259
+
3260
+ static void
3261
+ set_retry_failpoint (mongoc_ssl_opt_t * ssl_opts , bool network , uint32_t count )
3262
+ {
3263
+ mongoc_http_request_t req ;
3264
+ mongoc_http_response_t res ;
3265
+ bool r ;
3266
+ bson_error_t error = {0 };
3267
+
3268
+ _mongoc_http_request_init (& req );
3269
+ _mongoc_http_response_init (& res );
3270
+
3271
+ req .method = "POST" ;
3272
+ req .host = failpoint_server_ip ;
3273
+ req .port = failpoint_server_port ;
3274
+ if (network ) {
3275
+ req .path = "/set_failpoint/network" ;
3276
+ } else {
3277
+ req .path = "/set_failpoint/http" ;
3278
+ }
3279
+ req .extra_headers = "Content-Type: application/json\r\n" ;
3280
+ char count_json [25 ];
3281
+ sprintf (count_json , "{\"count\": %" PRIu32 "}" , count );
3282
+ req .body = count_json ;
3283
+ req .body_len = strlen (count_json );
3284
+
3285
+ r = _mongoc_http_send (& req , 10000 , true, ssl_opts , & res , & error );
3286
+ ASSERT_OR_PRINT (r , error );
3287
+ _mongoc_http_response_cleanup (& res );
3288
+ }
3289
+
3231
3290
/* ee_fixture is a fixture for the Explicit Encryption prose test. */
3232
3291
typedef struct {
3233
3292
bson_value_t key1ID ;
@@ -6232,6 +6291,88 @@ test_range_explicit_encryption_applies_defaults (void *unused)
6232
6291
mongoc_client_destroy (keyVaultClient );
6233
6292
}
6234
6293
6294
+ static void
6295
+ _test_retry_with_masterkey (const char * provider , bson_t * masterkey )
6296
+ {
6297
+ mongoc_client_t * keyvault_client = test_framework_new_default_client ();
6298
+ mongoc_client_encryption_t * client_encryption = _tls_test_make_client_encryption (keyvault_client , RETRY );
6299
+ bson_error_t error = {0 };
6300
+ bson_value_t keyid ;
6301
+ mongoc_client_encryption_datakey_opts_t * dkopts ;
6302
+ char * ca_file = test_framework_getenv_required ("MONGOC_TEST_CSFLE_TLS_CA_FILE" );
6303
+ char * pem_file = test_framework_getenv_required ("MONGOC_TEST_CSFLE_TLS_CERTIFICATE_KEY_FILE" );
6304
+ mongoc_ssl_opt_t ssl_opts = {.ca_file = ca_file , .pem_file = pem_file };
6305
+ bool res ;
6306
+
6307
+ bson_value_t to_encrypt = {.value_type = BSON_TYPE_INT32 , .value .v_int32 = 123 };
6308
+ bson_value_t encrypted_field = {0 };
6309
+ mongoc_client_encryption_encrypt_opts_t * encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
6310
+ mongoc_client_encryption_encrypt_opts_set_algorithm (encrypt_opts ,
6311
+ MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC );
6312
+
6313
+ reset_failpoints (& ssl_opts );
6314
+
6315
+ // Case 1: createDataKey and encrypt with TCP retry
6316
+ dkopts = mongoc_client_encryption_datakey_opts_new ();
6317
+ mongoc_client_encryption_datakey_opts_set_masterkey (dkopts , masterkey );
6318
+ set_retry_failpoint (& ssl_opts , true, 1 );
6319
+ res = mongoc_client_encryption_create_datakey (client_encryption , provider , dkopts , & keyid , & error );
6320
+ ASSERT_OR_PRINT (res , error );
6321
+
6322
+ set_retry_failpoint (& ssl_opts , true, 1 );
6323
+ mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts , & keyid );
6324
+ res = mongoc_client_encryption_encrypt (client_encryption , & to_encrypt , encrypt_opts , & encrypted_field , & error );
6325
+ ASSERT_OR_PRINT (res , error );
6326
+ bson_value_destroy (& keyid );
6327
+ bson_value_destroy (& encrypted_field );
6328
+ mongoc_client_encryption_datakey_opts_destroy (dkopts );
6329
+
6330
+ // Case 2: createDataKey and encrypt with HTTP retry
6331
+ dkopts = mongoc_client_encryption_datakey_opts_new ();
6332
+ mongoc_client_encryption_datakey_opts_set_masterkey (dkopts , masterkey );
6333
+ set_retry_failpoint (& ssl_opts , false, 1 );
6334
+ res = mongoc_client_encryption_create_datakey (client_encryption , provider , dkopts , & keyid , & error );
6335
+ ASSERT_OR_PRINT (res , error );
6336
+
6337
+ set_retry_failpoint (& ssl_opts , false, 1 );
6338
+ mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts , & keyid );
6339
+ res = mongoc_client_encryption_encrypt (client_encryption , & to_encrypt , encrypt_opts , & encrypted_field , & error );
6340
+ ASSERT_OR_PRINT (res , error );
6341
+ bson_value_destroy (& keyid );
6342
+ bson_value_destroy (& encrypted_field );
6343
+ mongoc_client_encryption_datakey_opts_destroy (dkopts );
6344
+
6345
+ // Case 3: createDataKey fails after too many retries
6346
+ dkopts = mongoc_client_encryption_datakey_opts_new ();
6347
+ mongoc_client_encryption_datakey_opts_set_masterkey (dkopts , masterkey );
6348
+ set_retry_failpoint (& ssl_opts , true, 4 );
6349
+ res = mongoc_client_encryption_create_datakey (client_encryption , provider , dkopts , & keyid , & error );
6350
+ ASSERT_ERROR_CONTAINS (error , MONGOC_ERROR_STREAM , MONGOC_ERROR_STREAM_SOCKET , "KMS request failed after" );
6351
+
6352
+ bson_value_destroy (& keyid );
6353
+ mongoc_client_encryption_datakey_opts_destroy (dkopts );
6354
+
6355
+ bson_free (ca_file );
6356
+ bson_free (pem_file );
6357
+ mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts );
6358
+ mongoc_client_encryption_destroy (client_encryption );
6359
+ mongoc_client_destroy (keyvault_client );
6360
+ }
6361
+
6362
+ /* Prose test 23: KMS Retry Tests */
6363
+ static void
6364
+ test_kms_retry (void * unused )
6365
+ {
6366
+ bson_t * aws_masterkey = tmp_bson (BSON_STR ({"region" : "r ", " key " : " k ", " endpoint " : " 127.0 .0 .1 :9003 "}));
6367
+ bson_t * azure_masterkey = tmp_bson (BSON_STR ({"keyVaultEndpoint" : "127.0.0.1:9003" , "keyName" : "foo" }));
6368
+ bson_t * gcp_masterkey = tmp_bson (BSON_STR (
6369
+ {"projectId" : "foo ", " location " : " bar ", " keyRing " : " baz ", " keyName " : " qux ", " endpoint " : " 127.0 .0 .1 :9003 "}));
6370
+
6371
+ _test_retry_with_masterkey ("aws" , aws_masterkey );
6372
+ _test_retry_with_masterkey ("azure" , azure_masterkey );
6373
+ _test_retry_with_masterkey ("gcp" , gcp_masterkey );
6374
+ }
6375
+
6235
6376
void
6236
6377
test_client_side_encryption_install (TestSuite * suite )
6237
6378
{
@@ -6412,6 +6553,12 @@ test_client_side_encryption_install (TestSuite *suite)
6412
6553
NULL ,
6413
6554
NULL ,
6414
6555
test_framework_skip_if_no_client_side_encryption );
6556
+ TestSuite_AddFull (suite ,
6557
+ "/client_side_encryption/kms_retry" ,
6558
+ test_kms_retry ,
6559
+ NULL ,
6560
+ NULL ,
6561
+ test_framework_skip_if_no_client_side_encryption );
6415
6562
6416
6563
TestSuite_AddFull (suite ,
6417
6564
"/client_side_encryption/explicit_encryption/case1" ,
0 commit comments