Skip to content

Commit 7c456a2

Browse files
authored
Merge branch 'main' into csharp734
2 parents 3bfba94 + 3669ba7 commit 7c456a2

File tree

10 files changed

+347
-23
lines changed

10 files changed

+347
-23
lines changed

build.cake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,15 @@ Task("TestSocks5Proxy")
265265
action: (BuildConfig buildConfig, Path testProject) =>
266266
RunTests(buildConfig, testProject, filter: "Category=\"Socks5Proxy\""));
267267

268+
Task("TestX509")
269+
.IsDependentOn("Build")
270+
.DoesForEach(
271+
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
272+
action: (BuildConfig buildConfig, Path testProject) =>
273+
RunTests(buildConfig, testProject, filter: "Category=\"X509\""));
274+
275+
Task("TestX509Net60").IsDependentOn("TestX509");
276+
268277
Task("Package")
269278
.IsDependentOn("PackageNugetPackages");
270279

evergreen/convert-client-cert-to-pkcs12.sh

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,39 @@
33
set -o errexit # Exit the script with an error if any of the commands fail
44

55
# Environment variables used as input:
6-
# CLIENT_PEM Path to mongo -orchestration's client.pem: must be set.
7-
# MONGO_X509_CLIENT_P12 Filename for client certificate in p12 format
6+
# CLIENT_PEM Path to mongo client.pem: must be set
7+
# P12_FILENAME Filename for client certificate in p12 format
8+
# P12_PASSWORD Password for client certificate in p12 format
9+
# P12_FRIENDLY_NAME Friendly name for client certificate in p12 format
10+
# OUT_CLIENT_PATH_VAR Name of the output variable containing the path of the p12 certificate
11+
# OUT_CLIENT_PASSWORD_VAR Name of the output variable containing the password for the p12 certificate
812
#
913
# Environment variables produced as output:
10-
# MONGODB_X509_CLIENT_P12_PATH Absolute path to client certificate in p12 format
11-
# MONGO_X509_CLIENT_CERTIFICATE_PASSWORD Password for client certificate
14+
# ${OUT_CLIENT_PATH_VAR} Absolute path to client certificate in p12 format (OUT_CLIENT_PATH_VAR contains the actual variable being exported)
15+
# ${OUT_CLIENT_PASSWORD_VAR} Password for client certificate (OUT_CLIENT_PASSWORD_VAR contains the actual variable being exported)
1216

1317

14-
CLIENT_PEM=${CLIENT_PEM:-nil}
15-
MONGO_X509_CLIENT_P12=${MONGO_X509_CLIENT_P12:-client.p12}
16-
MONGO_X509_CLIENT_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5}
18+
# Input environment variables and default values
19+
: "${CLIENT_PEM:=nil}"
20+
: "${P12_FRIENDLY_NAME:="Drivers Client Certificate"}"
21+
: "${P12_FILENAME:="client.p12"}"
22+
: "${P12_PASSWORD:="Picard-Alpha-Alpha-3-0-5"}"
23+
: "${OUT_CLIENT_PATH_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PATH"}"
24+
: "${OUT_CLIENT_PASSWORD_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"}"
1725

1826
if [[ "$CLIENT_PEM" == "nil" ]]; then
27+
echo "Error: CLIENT_PEM must be set."
1928
exit 1
2029
fi
2130

2231
openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "${CLIENT_PEM}" \
23-
-out "${MONGO_X509_CLIENT_P12}" \
24-
-name "Drivers Client Certificate" \
25-
-password "pass:${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD}"
32+
-out "${P12_FILENAME}" \
33+
-name "${P12_FRIENDLY_NAME}" \
34+
-password "pass:${P12_PASSWORD}"
2635

36+
# Determine path using realpath (compatible across macOS, Linux, and Windows)
2737
if [[ "$OS" =~ MAC|Mac|mac ]]; then
28-
# this function is not available on mac OS
38+
# Functionality to mimic `realpath` on macOS
2939
function realpath() {
3040
OURPWD=$PWD
3141
cd "$(dirname "$1")"
@@ -39,11 +49,17 @@ if [[ "$OS" =~ MAC|Mac|mac ]]; then
3949
echo "$REALPATH"
4050
}
4151
fi
42-
MONGO_X509_CLIENT_CERTIFICATE_PATH=$(realpath "${MONGO_X509_CLIENT_P12}")
52+
53+
CERT_PATH=$(realpath "${P12_FILENAME}")
4354

4455
if [[ "$OS" =~ Windows|windows ]]; then
45-
MONGO_X509_CLIENT_CERTIFICATE_PATH=$(cygpath -w "${MONGO_X509_CLIENT_CERTIFICATE_PATH}")
56+
CERT_PATH=$(cygpath -w "${CERT_PATH}")
4657
fi
4758

48-
export MONGO_X509_CLIENT_CERTIFICATE_PATH
49-
export MONGO_X509_CLIENT_CERTIFICATE_PASSWORD
59+
# Output environment variables
60+
export "${OUT_CLIENT_PASSWORD_VAR}"="${P12_PASSWORD}"
61+
export "${OUT_CLIENT_PATH_VAR}"="${CERT_PATH}"
62+
63+
echo "Exported variables:"
64+
echo "${OUT_CLIENT_PASSWORD_VAR}=${!OUT_CLIENT_PASSWORD_VAR}"
65+
echo "${OUT_CLIENT_PATH_VAR}=${!OUT_CLIENT_PATH_VAR}"

evergreen/evergreen.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,46 @@ functions:
10661066
FRAMEWORK=${FRAMEWORK} \
10671067
TARGET="TestSocks5Proxy" \
10681068
evergreen/run-tests.sh
1069+
1070+
setup-x509-tests:
1071+
- command: shell.exec
1072+
params:
1073+
shell: "bash"
1074+
include_expansions_in_env:
1075+
- "AWS_ACCESS_KEY_ID"
1076+
- "AWS_SECRET_ACCESS_KEY"
1077+
- "AWS_SESSION_TOKEN"
1078+
script: |
1079+
${DRIVERS_TOOLS}/.evergreen/secrets_handling/setup-secrets.sh drivers/atlas_connect
1080+
source secrets-export.sh
1081+
1082+
echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem
1083+
echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem
1084+
1085+
run-x509-tests:
1086+
- command: shell.exec
1087+
type: test
1088+
params:
1089+
shell: "bash"
1090+
working_dir: mongo-csharp-driver
1091+
script: |
1092+
source ../secrets-export.sh
1093+
${PREPARE_SHELL}
1094+
OS=${OS} \
1095+
evergreen/add-ca-certs.sh
1096+
P12_FRIENDLY_NAME="Drivers No-User Client Certificate" \
1097+
P12_FILENAME="client_no_user.p12" \
1098+
OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \
1099+
OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \
1100+
CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \
1101+
source evergreen/convert-client-cert-to-pkcs12.sh
1102+
MONGODB_URI="$ATLAS_X509_DEV" \
1103+
CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \
1104+
TOPOLOGY=${TOPOLOGY} \
1105+
OS=${OS} \
1106+
FRAMEWORK=${FRAMEWORK} \
1107+
TARGET="TestX509" \
1108+
evergreen/run-tests.sh
10691109
10701110
pre:
10711111
- func: fetch-source
@@ -1782,6 +1822,14 @@ tasks:
17821822
${PREPARE_SHELL}
17831823
CRYPT_SHARED_LIB_PATH="${CRYPT_SHARED_LIB_PATH}" DRIVER_VERSION="${PACKAGE_VERSION}" MONGODB_VERSION="${VERSION}" bash ./evergreen/run-tests.sh
17841824
1825+
- name: x509-auth-tests
1826+
commands:
1827+
- func: assume-ec2-role
1828+
- func: setup-x509-tests
1829+
- func: run-x509-tests
1830+
vars:
1831+
FRAMEWORK: net60
1832+
17851833
axes:
17861834
- id: version
17871835
display_name: MongoDB Version
@@ -2479,6 +2527,12 @@ buildvariants:
24792527
- name: test-gssapi-netstandard21
24802528
- name: test-gssapi-net60
24812529

2530+
- matrix_name: "x509-tests"
2531+
matrix_spec: { os: ["ubuntu-2004", "macos-14", "windows-64"], ssl: ["ssl"], version: ["latest"], topology: ["standalone"] }
2532+
display_name: "X509 tests ${version} ${os}"
2533+
tasks:
2534+
- name: x509-auth-tests
2535+
24822536
# Load balancer tests
24832537
- matrix_name: load-balancer-tests
24842538
matrix_spec: { version: ["5.0", "6.0", "7.0", "8.0", "rapid", "latest"], auth: "noauth", ssl: "nossl", topology: "sharded-cluster", os: "ubuntu-2004" }

src/MongoDB.Driver/BulkWriteInsertOneResult.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System;
1617
using MongoDB.Bson;
1718

1819
namespace MongoDB.Driver
@@ -25,6 +26,19 @@ public class BulkWriteInsertOneResult
2526
/// <summary>
2627
/// The id of the inserted document.
2728
/// </summary>
28-
public BsonValue InsertedId { get; init; }
29+
[Obsolete("InsertedId is deprecated and will be removed in future versions. Use DocumentId instead.")]
30+
public BsonValue InsertedId
31+
{
32+
get => BsonValue.Create(DocumentId);
33+
init
34+
{
35+
DocumentId = value;
36+
}
37+
}
38+
39+
/// <summary>
40+
/// The id of the inserted document.
41+
/// </summary>
42+
public object DocumentId { get; init; }
2943
}
3044
}

src/MongoDB.Driver/Core/Operations/ClientBulkWriteOperation.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ internal sealed class ClientBulkWriteOperation : RetryableWriteCommandOperationB
3232
{
3333
private readonly bool? _bypassDocumentValidation;
3434
private readonly bool _errorsOnly;
35-
private readonly Dictionary<int, BsonValue> _idsMap = new();
35+
private readonly Dictionary<int, object> _idsMap = new();
3636
private readonly BsonDocument _let;
3737
private readonly RenderArgs<BsonDocument> _renderArgs;
3838
private readonly IBatchableSource<BulkWriteModel> _writeModels;
@@ -337,7 +337,7 @@ private void PopulateIndividualResponses(IEnumerable<BsonDocument> individualRes
337337
_idsMap.TryGetValue(operationIndex, out var insertedId);
338338
bulkWriteResult.InsertResults.Add(operationIndex, new()
339339
{
340-
InsertedId = insertedId
340+
DocumentId = insertedId
341341
});
342342
}
343343
else if (writeModelType == typeof(BulkWriteUpdateOneModel<>) || writeModelType == typeof(BulkWriteUpdateManyModel<>) || writeModelType == typeof(BulkWriteReplaceOneModel<>))

src/MongoDB.Driver/Core/WireProtocol/Messages/CommandMessageSection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ internal sealed class ClientBulkWriteOpsCommandMessageSection : BatchableCommand
133133
{
134134
public ClientBulkWriteOpsCommandMessageSection(
135135
IBatchableSource<BulkWriteModel> operations,
136-
Dictionary<int, BsonValue> idsMap,
136+
Dictionary<int, object> idsMap,
137137
int? maxBatchCount,
138138
int? maxDocumentSize,
139139
RenderArgs<BsonDocument> renderArgs)
@@ -144,7 +144,7 @@ public ClientBulkWriteOpsCommandMessageSection(
144144
RenderArgs = renderArgs;
145145
}
146146

147-
public Dictionary<int, BsonValue> IdsMap { get; }
147+
public Dictionary<int, object> IdsMap { get; }
148148
public new IBatchableSource<BulkWriteModel> Documents { get; }
149149
public RenderArgs<BsonDocument> RenderArgs { get; }
150150
}

src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/ClientBulkWriteOpsSectionFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ internal sealed class ClientBulkWriteOpsSectionFormatter : ICommandMessageSectio
3232
private MemoryStream _nsInfoMemoryStream;
3333
private BsonBinaryWriter _nsInfoWriter;
3434
private IBsonSerializerRegistry _serializerRegistry;
35-
private Dictionary<int, BsonValue> _idsMap;
35+
private Dictionary<int, object> _idsMap;
3636
private int _currentIndex;
3737

3838
public ClientBulkWriteOpsSectionFormatter(long? maxSize)
@@ -150,7 +150,7 @@ public void RenderInsertOne<TDocument>(RenderArgs<BsonDocument> renderArgs, Bson
150150
WriteStartModel(serializationContext, "insert", model);
151151
var documentSerializer = _serializerRegistry.GetSerializer<TDocument>();
152152
var documentId = documentSerializer.SetDocumentIdIfMissing(null, model.Document);
153-
_idsMap[_currentIndex] = BsonValue.Create(documentId);
153+
_idsMap[_currentIndex] = documentId;
154154
serializationContext.Writer.WriteName("document");
155155
documentSerializer.Serialize(serializationContext, model.Document);
156156
WriteEndModel(serializationContext);
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Threading.Tasks;
19+
using FluentAssertions;
20+
using MongoDB.Bson.Serialization;
21+
using MongoDB.Driver.Core.Misc;
22+
using MongoDB.Driver.TestHelpers;
23+
using MongoDB.TestHelpers.XunitExtensions;
24+
using Xunit;
25+
26+
namespace MongoDB.Driver.Tests.Jira;
27+
28+
public class CSharp5697Tests : IntegrationTest<CSharp5697Tests.ClassFixture>
29+
{
30+
public CSharp5697Tests(ClassFixture fixture)
31+
: base(fixture, server => server.Supports(Feature.ClientBulkWrite))
32+
{
33+
}
34+
35+
[Theory]
36+
[ParameterAttributeData]
37+
public async Task ClientBulkWrite_supports_complex_id([Values(true, false)] bool async)
38+
{
39+
var id = async ? "1" : "2";
40+
var options = new ClientBulkWriteOptions { VerboseResult = true };
41+
BulkWriteModel[] models =
42+
[
43+
new BulkWriteInsertOneModel<Document>(
44+
Fixture.Collection.CollectionNamespace,
45+
new Document(new DocumentId(id)))
46+
];
47+
48+
var result = async ?
49+
await Fixture.Client.BulkWriteAsync(models, options) :
50+
Fixture.Client.BulkWrite(models, options);
51+
52+
result.InsertResults[0].DocumentId.Should().BeOfType<DocumentId>()
53+
.Subject.Key.Should().Be(id);
54+
}
55+
56+
public class Document
57+
{
58+
public Document(DocumentId id)
59+
{
60+
Id = id;
61+
}
62+
63+
public DocumentId Id { get; }
64+
}
65+
66+
public class DocumentId
67+
{
68+
public DocumentId(string key)
69+
{
70+
Key = key;
71+
}
72+
73+
public string Key { get; }
74+
}
75+
76+
public sealed class DocumentIdSerializer : IBsonSerializer<DocumentId>
77+
{
78+
public Type ValueType => typeof(DocumentId);
79+
80+
public DocumentId Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
81+
=> new DocumentId(context.Reader.ReadString());
82+
83+
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DocumentId value)
84+
=> context.Writer.WriteString(value.Key);
85+
86+
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
87+
{
88+
var id = (DocumentId)value;
89+
Serialize(context, args, id);
90+
}
91+
92+
object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
93+
=> Deserialize(context, args);
94+
}
95+
96+
public class ClassFixture : MongoCollectionFixture<Document>
97+
{
98+
public ClassFixture()
99+
{
100+
BsonSerializer.RegisterSerializer( new DocumentIdSerializer());
101+
}
102+
103+
protected override IEnumerable<Document> InitialData => null;
104+
}
105+
}
106+

tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedClientBulkWriteOperation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static BsonDocument ConvertClientBulkWriteResult(ClientBulkWriteResult re
102102
{ "deletedCount", (int)result.DeletedCount },
103103
{
104104
"insertResults", ConvertResults(result.InsertResults,
105-
item => new() { { "insertedId", item.InsertedId } })
105+
item => new() { { "insertedId", BsonValue.Create(item.DocumentId) } })
106106
},
107107
{
108108
"updateResults", ConvertResults(result.UpdateResults,

0 commit comments

Comments
 (0)