From eeac139a250370e0297e820fa443ee03b1f3017d Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 15 Aug 2025 09:45:41 +0200 Subject: [PATCH 01/12] CSHARP-5581: Test MONGODB-X509 on cloud-dev --- build.cake | 7 ++ evergreen/convert-client-cert-to-pkcs12.sh | 89 ++++++++++++++------- evergreen/evergreen.yml | 48 +++++++++++ evergreen/run-tests.sh | 4 + tests/MongoDB.Driver.Tests/X509Tests.cs | 93 ++++++++++++++++++++++ 5 files changed, 214 insertions(+), 27 deletions(-) create mode 100644 tests/MongoDB.Driver.Tests/X509Tests.cs diff --git a/build.cake b/build.cake index 1fcd96a6554..17440fe000a 100644 --- a/build.cake +++ b/build.cake @@ -254,6 +254,13 @@ Task("TestCsfleWithGcpKms") action: (BuildConfig buildConfig, Path testProject) => RunTests(buildConfig, testProject, filter: "Category=\"CsfleGCPKMS\"")); +Task("TestX509") + .IsDependentOn("Build") + .DoesForEach( + items: GetFiles("./**/MongoDB.Driver.Tests.csproj"), + action: (BuildConfig buildConfig, Path testProject) => + RunTests(buildConfig, testProject, filter: "Category=\"X509\"")); + Task("Package") .IsDependentOn("PackageNugetPackages"); diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index ee8a5939df0..ed50920e1cb 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -15,35 +15,70 @@ CLIENT_PEM=${CLIENT_PEM:-nil} MONGO_X509_CLIENT_P12=${MONGO_X509_CLIENT_P12:-client.p12} MONGO_X509_CLIENT_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} -if [[ "$CLIENT_PEM" == "nil" ]]; then - exit 1 -fi +CLIENT_NO_USER_PEM=${CLIENT_PEM:-nil} +MONGO_X509_CLIENT_NO_USER_P12=${MONGO_X509_CLIENT_NO_USER_P12:-client.p12} +MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} + +function create_p12 { + local PEM_FILE=$1 + local P12_FILE=$2 + local PASSWORD=$3 + + if [[ ! -f "$PEM_FILE" ]]; then + echo "Warning: PEM file '$PEM_FILE' does not exist. Skipping generation of '$P12_FILE'." + return 1 + fi + + openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "$PEM_FILE" \ + -out "$P12_FILE" \ + -name "Drivers Client Certificate" \ + -password "pass:${PASSWORD}" +} -openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "${CLIENT_PEM}" \ - -out "${MONGO_X509_CLIENT_P12}" \ - -name "Drivers Client Certificate" \ - -password "pass:${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD}" - -if [[ "$OS" =~ MAC|Mac|mac ]]; then - # this function is not available on mac OS - function realpath() { - OURPWD=$PWD - cd "$(dirname "$1")" - LINK=$(readlink "$(basename "$1")") - while [ "$LINK" ]; do - cd "$(dirname "$LINK")" +function get_realpath { + local FILE=$1 + + if [[ "$OS" =~ MAC|Mac|mac ]]; then + # realpath function for Mac OS + function realpath() { + OURPWD=$PWD + cd "$(dirname "$1")" LINK=$(readlink "$(basename "$1")") - done - REALPATH="$PWD/$(basename "$1")" - cd "$OURPWD" - echo "$REALPATH" - } -fi -MONGO_X509_CLIENT_CERTIFICATE_PATH=$(realpath "${MONGO_X509_CLIENT_P12}") + while [ "$LINK" ]; do + cd "$(dirname "$LINK")" + LINK=$(readlink "$(basename "$1")") + done + REALPATH="$PWD/$(basename "$1")" + cd "$OURPWD" + echo "$REALPATH" + } + fi + + if [[ "$OS" =~ Windows|windows ]]; then + echo "$(cygpath -w "$FILE")" + else + echo "$(realpath "$FILE")" + fi +} -if [[ "$OS" =~ Windows|windows ]]; then - MONGO_X509_CLIENT_CERTIFICATE_PATH=$(cygpath -w "${MONGO_X509_CLIENT_CERTIFICATE_PATH}") +# Create the primary client's p12 certificate if the PEM file exists +if create_p12 "$CLIENT_PEM" "$MONGO_X509_CLIENT_P12" "$MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"; then + MONGO_X509_CLIENT_CERTIFICATE_PATH=$(get_realpath "$MONGO_X509_CLIENT_P12") + export MONGO_X509_CLIENT_CERTIFICATE_PATH + export MONGO_X509_CLIENT_CERTIFICATE_PASSWORD + echo "Primary certificate path: $MONGO_X509_CLIENT_CERTIFICATE_PATH" + echo "Primary certificate password: $MONGO_X509_CLIENT_CERTIFICATE_PASSWORD" +else + echo "Skipping primary certificate creation." fi -export MONGO_X509_CLIENT_CERTIFICATE_PATH -export MONGO_X509_CLIENT_CERTIFICATE_PASSWORD +# Create the secondary "No User" client's p12 certificate if the PEM file exists +if create_p12 "$CLIENT_NO_USER_PEM" "$MONGO_X509_CLIENT_NO_USER_P12" "$MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD"; then + MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH=$(get_realpath "$MONGO_X509_CLIENT_NO_USER_P12") + export MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH + export MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD + echo "Secondary ('No User') certificate path: $MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" + echo "Secondary ('No User') certificate password: $MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" +else + echo "Skipping secondary ('No User') certificate creation." +fi \ No newline at end of file diff --git a/evergreen/evergreen.yml b/evergreen/evergreen.yml index f6f961402ce..f2cf1e829ed 100644 --- a/evergreen/evergreen.yml +++ b/evergreen/evergreen.yml @@ -359,6 +359,42 @@ functions: cd ${DRIVERS_TOOLS}/.evergreen DRIVERS_TOOLS=${DRIVERS_TOOLS} MONGODB_URI=${MONGODB_URI} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh stop + + setup-x509-tests: + - command: shell.exec + params: + shell: "bash" + include_expansions_in_env: + - "AWS_ACCESS_KEY_ID" + - "AWS_SECRET_ACCESS_KEY" + - "AWS_SESSION_TOKEN" + script: | + ${DRIVERS_TOOLS}/.evergreen/secrets_handling/setup-secrets.sh drivers/atlas_connect + source secrets-export.sh + + echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem + echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NOUSER_CERT.pem + + run-x509-tests: + - command: shell.exec + type: test + params: + shell: "bash" + working_dir: mongo-csharp-driver + script: | + source ../secrets-export.sh + ${PREPARE_SHELL} + OS=${OS} \ + evergreen/add-ca-certs.sh + MONGODB_URI="$ATLAS_X509_DEV" \ + CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \ + CLIENT_NOUSER_PEM=${DRIVERS_TOOLS}/CLIENT_NOUSER_CERT.pem \ + TOPOLOGY=${TOPOLOGY} \ + OS=${OS} \ + FRAMEWORK=${FRAMEWORK} \ + TARGET="TestX509" \ + evergreen/run-tests.sh + run-unit-tests: - command: shell.exec type: test @@ -1219,6 +1255,12 @@ tasks: - func: run-aws-auth-test-with-aws-ECS-credentials - func: run-aws-auth-test-with-aws-web-identity-credentials + - name: x509-auth-tests + commands: + - func: assume-ec2-role + - func: setup-x509-tests + - func: run-x509-tests + - name: stable-api-tests-net472 commands: - func: setup-csfle-secrets @@ -2417,6 +2459,12 @@ buildvariants: - name: test-gssapi-netstandard21 - name: test-gssapi-net60 +- matrix_name: "x509-tests" + matrix_spec: { os: ["ubuntu-2004", "macos-14", "windows-64"], ssl: ["ssl"], version: ["latest"], topology: ["standalone"] } + display_name: "X509 tests ${version} ${os}" + tasks: + - name: x509-auth-tests + # Load balancer tests - matrix_name: load-balancer-tests matrix_spec: { version: ["5.0", "6.0", "7.0", "8.0", "rapid", "latest"], auth: "noauth", ssl: "nossl", topology: "sharded-cluster", os: "ubuntu-2004" } diff --git a/evergreen/run-tests.sh b/evergreen/run-tests.sh index 6ec9620ff3b..2fe52052365 100755 --- a/evergreen/run-tests.sh +++ b/evergreen/run-tests.sh @@ -133,6 +133,10 @@ if [[ "$CLIENT_PEM" != "nil" ]]; then CLIENT_PEM=${CLIENT_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi +if [[ "$CLIENT_NOUSER_PEM" != "nil" ]]; then + CLIENT_NOUSER_PEM=${CLIENT_NOUSER_PEM} source evergreen/convert-client-cert-to-pkcs12.sh +fi + if [[ -z "$MONGO_X509_CLIENT_CERTIFICATE_PATH" && -z "$MONGO_X509_CLIENT_CERTIFICATE_PASSWORD" ]]; then # technically the above condiion will be always true since CLIENT_PEM is always set and # convert-client-cert-to-pkcs12 always assigns these env variables, but leaving this condition in case diff --git a/tests/MongoDB.Driver.Tests/X509Tests.cs b/tests/MongoDB.Driver.Tests/X509Tests.cs new file mode 100644 index 00000000000..ac5fa261019 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/X509Tests.cs @@ -0,0 +1,93 @@ +/* Copyright 2010-present MongoDB Inc. + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using FluentAssertions; +using MongoDB.Bson; +using MongoDB.Driver.Core.Clusters.ServerSelectors; +using MongoDB.Driver.Core.Misc; +using MongoDB.Driver.Core.TestHelpers.XunitExtensions; +using MongoDB.TestHelpers.XunitExtensions; +using Xunit; + +namespace MongoDB.Driver.Tests; + +[Trait("Category", "Integration")] +[Trait("Category", "X509")] +public class X509Tests +{ + [Theory] + [ParameterAttributeData] + public void Authentication_succeeds_with_MONGODB_X509_mechanism( + [Values(false, true)] bool async) + { + RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH", isDefined: true); + RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD", isDefined: true); + RequireServer.Check().Tls(required: true); + + var pathToClientCertificate = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH"); + var password = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"); + var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + + var settings = DriverTestConfiguration.GetClientSettings().Clone(); + settings.Credential = MongoCredential.CreateMongoX509Credential(); + settings.SslSettings = settings.SslSettings.Clone(); + settings.SslSettings.ClientCertificates = new[] { clientCertificate }; + + AssertAuthenticationSucceeds(settings, async, speculativeAuthenticatationShouldSucceedIfPossible: true); + } + + private void AssertAuthenticationSucceeds( + MongoClientSettings settings, + bool async, + bool speculativeAuthenticatationShouldSucceedIfPossible = true) + { + // If we don't use a DisposableClient, the second run of AuthenticationSucceedsWithMongoDB_X509_mechanism + // will fail because the backing Cluster's connections will be associated with a dropped user + using (var client = DriverTestConfiguration.CreateMongoClient(settings)) + { + // The first command executed with the MongoClient triggers either the sync or async variation of the + // MongoClient's IAuthenticator + if (async) + { + _ = client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList(); + } + else + { + _ = client.ListDatabaseNames().ToList(); + } + if (Feature.SpeculativeAuthentication.IsSupported(CoreTestConfiguration.MaxWireVersion) && + speculativeAuthenticatationShouldSucceedIfPossible) + { + var serverSelector = new ReadPreferenceServerSelector(settings.ReadPreference); + var server = client.GetClusterInternal().SelectServer(OperationContext.NoTimeout, serverSelector); + var channel = server.GetChannel(OperationContext.NoTimeout); + var helloResult = channel.ConnectionDescription.HelloResult; + helloResult.SpeculativeAuthenticate.Should().NotBeNull(); + } + } + } + + private string GetRfc2253FormattedUsernameFromX509ClientCertificate(X509Certificate2 certificate) + { + var distinguishedName = certificate.SubjectName.Name; + // Authentication will fail if we don't remove the delimiting spaces, even if we add the username WITH the + // delimiting spaces. + var nameWithoutDelimitingSpaces = string.Join(",", distinguishedName.Split(',').Select(s => s.Trim())); + return nameWithoutDelimitingSpaces.Replace("S=", "ST="); + } +} \ No newline at end of file From b5b29d1cd75456dc00784a36868f0a915e1875ab Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:57:17 +0200 Subject: [PATCH 02/12] Small correction --- evergreen/evergreen.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evergreen/evergreen.yml b/evergreen/evergreen.yml index f2cf1e829ed..3f67e388830 100644 --- a/evergreen/evergreen.yml +++ b/evergreen/evergreen.yml @@ -373,7 +373,7 @@ functions: source secrets-export.sh echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem - echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NOUSER_CERT.pem + echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem run-x509-tests: - command: shell.exec @@ -388,7 +388,7 @@ functions: evergreen/add-ca-certs.sh MONGODB_URI="$ATLAS_X509_DEV" \ CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \ - CLIENT_NOUSER_PEM=${DRIVERS_TOOLS}/CLIENT_NOUSER_CERT.pem \ + CLIENT_NO_USER_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \ TOPOLOGY=${TOPOLOGY} \ OS=${OS} \ FRAMEWORK=${FRAMEWORK} \ From b5698cb0fb1b15c0dbc4a46b014e766490cb1089 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:57:35 +0200 Subject: [PATCH 03/12] Small corrections --- evergreen/convert-client-cert-to-pkcs12.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index ed50920e1cb..7e5727d182d 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -15,7 +15,7 @@ CLIENT_PEM=${CLIENT_PEM:-nil} MONGO_X509_CLIENT_P12=${MONGO_X509_CLIENT_P12:-client.p12} MONGO_X509_CLIENT_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} -CLIENT_NO_USER_PEM=${CLIENT_PEM:-nil} +CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM:-nil} MONGO_X509_CLIENT_NO_USER_P12=${MONGO_X509_CLIENT_NO_USER_P12:-client.p12} MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} From 887c07294b8af8f6a9835eafef915027aab0b1df Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 15 Aug 2025 13:12:51 +0200 Subject: [PATCH 04/12] Small fix --- evergreen/convert-client-cert-to-pkcs12.sh | 3 +- tests/MongoDB.Driver.Tests/X509Tests.cs | 143 ++++++++++++--------- 2 files changed, 80 insertions(+), 66 deletions(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index 7e5727d182d..9f4a8e4f210 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -16,7 +16,7 @@ MONGO_X509_CLIENT_P12=${MONGO_X509_CLIENT_P12:-client.p12} MONGO_X509_CLIENT_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM:-nil} -MONGO_X509_CLIENT_NO_USER_P12=${MONGO_X509_CLIENT_NO_USER_P12:-client.p12} +MONGO_X509_CLIENT_NO_USER_P12=${MONGO_X509_CLIENT_NO_USER_P12:-client_no_user.p12} MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} function create_p12 { @@ -37,7 +37,6 @@ function create_p12 { function get_realpath { local FILE=$1 - if [[ "$OS" =~ MAC|Mac|mac ]]; then # realpath function for Mac OS function realpath() { diff --git a/tests/MongoDB.Driver.Tests/X509Tests.cs b/tests/MongoDB.Driver.Tests/X509Tests.cs index ac5fa261019..b87af8784ef 100644 --- a/tests/MongoDB.Driver.Tests/X509Tests.cs +++ b/tests/MongoDB.Driver.Tests/X509Tests.cs @@ -14,12 +14,8 @@ */ using System; -using System.Linq; using System.Security.Cryptography.X509Certificates; using FluentAssertions; -using MongoDB.Bson; -using MongoDB.Driver.Core.Clusters.ServerSelectors; -using MongoDB.Driver.Core.Misc; using MongoDB.Driver.Core.TestHelpers.XunitExtensions; using MongoDB.TestHelpers.XunitExtensions; using Xunit; @@ -30,64 +26,83 @@ namespace MongoDB.Driver.Tests; [Trait("Category", "X509")] public class X509Tests { - [Theory] - [ParameterAttributeData] - public void Authentication_succeeds_with_MONGODB_X509_mechanism( - [Values(false, true)] bool async) - { - RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH", isDefined: true); - RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD", isDefined: true); - RequireServer.Check().Tls(required: true); - - var pathToClientCertificate = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH"); - var password = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"); - var clientCertificate = new X509Certificate2(pathToClientCertificate, password); - - var settings = DriverTestConfiguration.GetClientSettings().Clone(); - settings.Credential = MongoCredential.CreateMongoX509Credential(); - settings.SslSettings = settings.SslSettings.Clone(); - settings.SslSettings.ClientCertificates = new[] { clientCertificate }; - - AssertAuthenticationSucceeds(settings, async, speculativeAuthenticatationShouldSucceedIfPossible: true); - } - - private void AssertAuthenticationSucceeds( - MongoClientSettings settings, - bool async, - bool speculativeAuthenticatationShouldSucceedIfPossible = true) - { - // If we don't use a DisposableClient, the second run of AuthenticationSucceedsWithMongoDB_X509_mechanism - // will fail because the backing Cluster's connections will be associated with a dropped user - using (var client = DriverTestConfiguration.CreateMongoClient(settings)) - { - // The first command executed with the MongoClient triggers either the sync or async variation of the - // MongoClient's IAuthenticator - if (async) - { - _ = client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList(); - } - else - { - _ = client.ListDatabaseNames().ToList(); - } - if (Feature.SpeculativeAuthentication.IsSupported(CoreTestConfiguration.MaxWireVersion) && - speculativeAuthenticatationShouldSucceedIfPossible) - { - var serverSelector = new ReadPreferenceServerSelector(settings.ReadPreference); - var server = client.GetClusterInternal().SelectServer(OperationContext.NoTimeout, serverSelector); - var channel = server.GetChannel(OperationContext.NoTimeout); - var helloResult = channel.ConnectionDescription.HelloResult; - helloResult.SpeculativeAuthenticate.Should().NotBeNull(); - } - } - } - - private string GetRfc2253FormattedUsernameFromX509ClientCertificate(X509Certificate2 certificate) - { - var distinguishedName = certificate.SubjectName.Name; - // Authentication will fail if we don't remove the delimiting spaces, even if we add the username WITH the - // delimiting spaces. - var nameWithoutDelimitingSpaces = string.Join(",", distinguishedName.Split(',').Select(s => s.Trim())); - return nameWithoutDelimitingSpaces.Replace("S=", "ST="); - } + const string MONGODB_X509_CLIENT_CERTIFICATE_PATH = "MONGO_X509_CLIENT_CERTIFICATE_PATH"; + const string MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD = "MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"; + + const string MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH = "MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH"; + const string MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD = "MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD"; + + [Fact] + public void Authentication_succeeds_with_MONGODB_X509_mechanism() + { + RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true); + RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); + RequireServer.Check().Tls(required: true); + + var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); + var password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); + var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + + var settings = DriverTestConfiguration.GetClientSettings().Clone(); + //settings.Credential = MongoCredential.CreateMongoX509Credential(); + settings.SslSettings = settings.SslSettings.Clone(); + settings.SslSettings.ClientCertificates = [clientCertificate]; + + AssertAuthenticationSucceeds(settings); + } + + [Fact] + public void Authentication_fails_with_MONGODB_X509_mechanism_when_username_is_wrong() + { + RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true); + RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); + RequireServer.Check().Tls(required: true); + + var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); + var password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); + var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + + var settings = DriverTestConfiguration.GetClientSettings().Clone(); + settings.Credential = MongoCredential.CreateMongoX509Credential("wrong_username"); + settings.SslSettings = settings.SslSettings.Clone(); + settings.SslSettings.ClientCertificates = [clientCertificate]; + + AssertAuthenticationFails(settings); + } + + [Fact] + public void Authentication_fails_with_MONGODB_X509_mechanism_when_user_is_not_in_database() + { + RequireEnvironment.Check().EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH, isDefined: true); + RequireEnvironment.Check().EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD, isDefined: true); + RequireServer.Check().Tls(required: true); + + var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH); + var password = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD); + var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + + var settings = DriverTestConfiguration.GetClientSettings().Clone(); + //settings.Credential = MongoCredential.CreateMongoX509Credential(); + settings.SslSettings = settings.SslSettings.Clone(); + settings.SslSettings.ClientCertificates = [clientCertificate]; + + AssertAuthenticationFails(settings); + } + + private void AssertAuthenticationSucceeds(MongoClientSettings settings) + { + using var client = DriverTestConfiguration.CreateMongoClient(settings); + _ = client.ListDatabaseNames().ToList(); + } + + private void AssertAuthenticationFails(MongoClientSettings settings) + { + using var client = DriverTestConfiguration.CreateMongoClient(settings); + var exception = Record.Exception(() => client.ListDatabaseNames().ToList()); + exception.Should().BeOfType(); + + // var innerException = exception.InnerException; + // innerException.Should().BeOfType(); + // innerException.Message.Should().Contain("Could not find user"); + } } \ No newline at end of file From 86ac517877f5505b36ce93590e307233387a28d2 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Fri, 15 Aug 2025 14:53:12 +0200 Subject: [PATCH 05/12] Various fixes --- evergreen/convert-client-cert-to-pkcs12.sh | 126 +++++++++------------ evergreen/run-tests.sh | 9 +- tests/MongoDB.Driver.Tests/X509Tests.cs | 5 - 3 files changed, 60 insertions(+), 80 deletions(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index 9f4a8e4f210..871071e243e 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -2,82 +2,62 @@ set -o errexit # Exit the script with an error if any of the commands fail -# Environment variables used as input: -# CLIENT_PEM Path to mongo -orchestration's client.pem: must be set. -# MONGO_X509_CLIENT_P12 Filename for client certificate in p12 format -# -# Environment variables produced as output: -# MONGODB_X509_CLIENT_P12_PATH Absolute path to client certificate in p12 format -# MONGO_X509_CLIENT_CERTIFICATE_PASSWORD Password for client certificate - - -CLIENT_PEM=${CLIENT_PEM:-nil} -MONGO_X509_CLIENT_P12=${MONGO_X509_CLIENT_P12:-client.p12} -MONGO_X509_CLIENT_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} - -CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM:-nil} -MONGO_X509_CLIENT_NO_USER_P12=${MONGO_X509_CLIENT_NO_USER_P12:-client_no_user.p12} -MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD=${MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD:-Picard-Alpha-Alpha-3-0-5} - -function create_p12 { - local PEM_FILE=$1 - local P12_FILE=$2 - local PASSWORD=$3 - - if [[ ! -f "$PEM_FILE" ]]; then - echo "Warning: PEM file '$PEM_FILE' does not exist. Skipping generation of '$P12_FILE'." - return 1 - fi - - openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "$PEM_FILE" \ - -out "$P12_FILE" \ - -name "Drivers Client Certificate" \ - -password "pass:${PASSWORD}" -} +# Input environment variables +: "${CLIENT_PEM_VAR_NAME:="CLIENT_PEM"}" # Name of the input variable for the client.pem file +: "${OUTPUT_VAR_PREFIX:="MONGO_X509_CLIENT"}" # Prefix for output environment variables +: "${CERTIFICATE_NAME:="Drivers Client Certificate"}" # Name for the exported certificate + +#todo, need to take the input name for client file and password, and not use the convoluted system we have +#I think I need to add those to the input environment variables and then use those in the export down here (where the default values for output variables are) + +CLIENT_PEM=${!CLIENT_PEM_VAR_NAME:-nil} +OUT_CLIENT_P12_VAR="${OUTPUT_VAR_PREFIX}_CLIENT_P12" +OUT_CLIENT_PASSWORD_VAR="${OUTPUT_VAR_PREFIX}_CERTIFICATE_PASSWORD" +OUT_CLIENT_PATH_VAR="${OUTPUT_VAR_PREFIX}_CERTIFICATE_PATH" + +# Default values for output variables (can be overridden via the environment) +export "${OUT_CLIENT_P12_VAR}"="${!OUT_CLIENT_P12_VAR:-client.p12}" +export "${OUT_CLIENT_PASSWORD_VAR}"="${!OUT_CLIENT_PASSWORD_VAR:-Picard-Alpha-Alpha-3-0-5}" + +if [[ "$CLIENT_PEM" == "nil" ]]; then + echo "Error: ${CLIENT_PEM_VAR_NAME} must be set." + exit 1 +fi -function get_realpath { - local FILE=$1 - if [[ "$OS" =~ MAC|Mac|mac ]]; then - # realpath function for Mac OS - function realpath() { - OURPWD=$PWD - cd "$(dirname "$1")" +P12_FILENAME=${!OUT_CLIENT_P12_VAR} +CERT_PASSWORD=${!OUT_CLIENT_PASSWORD_VAR} + +openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "${CLIENT_PEM}" \ + -out "${P12_FILENAME}" \ + -name "${CERTIFICATE_NAME}" \ + -password "pass:${CERT_PASSWORD}" + +# Determine path using realpath (compatible across macOS, Linux, and Windows) +if [[ "$OS" =~ MAC|Mac|mac ]]; then + # Functionality to mimic `realpath` on macOS + function realpath() { + OURPWD=$PWD + cd "$(dirname "$1")" + LINK=$(readlink "$(basename "$1")") + while [ "$LINK" ]; do + cd "$(dirname "$LINK")" LINK=$(readlink "$(basename "$1")") - while [ "$LINK" ]; do - cd "$(dirname "$LINK")" - LINK=$(readlink "$(basename "$1")") - done - REALPATH="$PWD/$(basename "$1")" - cd "$OURPWD" - echo "$REALPATH" - } - fi + done + REALPATH="$PWD/$(basename "$1")" + cd "$OURPWD" + echo "$REALPATH" + } +fi - if [[ "$OS" =~ Windows|windows ]]; then - echo "$(cygpath -w "$FILE")" - else - echo "$(realpath "$FILE")" - fi -} +CERT_PATH=$(realpath "${P12_FILENAME}") -# Create the primary client's p12 certificate if the PEM file exists -if create_p12 "$CLIENT_PEM" "$MONGO_X509_CLIENT_P12" "$MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"; then - MONGO_X509_CLIENT_CERTIFICATE_PATH=$(get_realpath "$MONGO_X509_CLIENT_P12") - export MONGO_X509_CLIENT_CERTIFICATE_PATH - export MONGO_X509_CLIENT_CERTIFICATE_PASSWORD - echo "Primary certificate path: $MONGO_X509_CLIENT_CERTIFICATE_PATH" - echo "Primary certificate password: $MONGO_X509_CLIENT_CERTIFICATE_PASSWORD" -else - echo "Skipping primary certificate creation." +if [[ "$OS" =~ Windows|windows ]]; then + CERT_PATH=$(cygpath -w "${CERT_PATH}") fi -# Create the secondary "No User" client's p12 certificate if the PEM file exists -if create_p12 "$CLIENT_NO_USER_PEM" "$MONGO_X509_CLIENT_NO_USER_P12" "$MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD"; then - MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH=$(get_realpath "$MONGO_X509_CLIENT_NO_USER_P12") - export MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH - export MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD - echo "Secondary ('No User') certificate path: $MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" - echo "Secondary ('No User') certificate password: $MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" -else - echo "Skipping secondary ('No User') certificate creation." -fi \ No newline at end of file +export "${OUT_CLIENT_PATH_VAR}"="${CERT_PATH}" + +echo "Exported variables:" +echo "${OUT_CLIENT_P12_VAR}=${!OUT_CLIENT_P12_VAR}" +echo "${OUT_CLIENT_PASSWORD_VAR}=${!OUT_CLIENT_PASSWORD_VAR}" +echo "${OUT_CLIENT_PATH_VAR}=${!OUT_CLIENT_PATH_VAR}" \ No newline at end of file diff --git a/evergreen/run-tests.sh b/evergreen/run-tests.sh index 2fe52052365..ce49752642e 100755 --- a/evergreen/run-tests.sh +++ b/evergreen/run-tests.sh @@ -29,6 +29,7 @@ TOPOLOGY=${TOPOLOGY:-server} COMPRESSOR=${COMPRESSOR:-none} OCSP_TLS_SHOULD_SUCCEED=${OCSP_TLS_SHOULD_SUCCEED:-nil} CLIENT_PEM=${CLIENT_PEM:-nil} +CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM:-nil} PLATFORM=${PLATFORM:-nil} TARGET=${TARGET:-Test} FRAMEWORK=${FRAMEWORK:-nil} @@ -133,8 +134,12 @@ if [[ "$CLIENT_PEM" != "nil" ]]; then CLIENT_PEM=${CLIENT_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi -if [[ "$CLIENT_NOUSER_PEM" != "nil" ]]; then - CLIENT_NOUSER_PEM=${CLIENT_NOUSER_PEM} source evergreen/convert-client-cert-to-pkcs12.sh +if [[ "$CLIENT_NO_USER_PEM" != "nil" ]]; then + export CLIENT_PEM_VAR_NAME="CLIENT_NO_USER_PEM" + export OUTPUT_VAR_PREFIX="MONGO_X509_CLIENT_NO_USER" + export CERTIFICATE_NAME="Drivers No-User Client Certificate" + export MONGO_X509_CLIENT_NO_USER_CLIENT_P12="client_no_user.p12" + CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi if [[ -z "$MONGO_X509_CLIENT_CERTIFICATE_PATH" && -z "$MONGO_X509_CLIENT_CERTIFICATE_PASSWORD" ]]; then diff --git a/tests/MongoDB.Driver.Tests/X509Tests.cs b/tests/MongoDB.Driver.Tests/X509Tests.cs index b87af8784ef..12d3124341e 100644 --- a/tests/MongoDB.Driver.Tests/X509Tests.cs +++ b/tests/MongoDB.Driver.Tests/X509Tests.cs @@ -44,8 +44,6 @@ public void Authentication_succeeds_with_MONGODB_X509_mechanism() var clientCertificate = new X509Certificate2(pathToClientCertificate, password); var settings = DriverTestConfiguration.GetClientSettings().Clone(); - //settings.Credential = MongoCredential.CreateMongoX509Credential(); - settings.SslSettings = settings.SslSettings.Clone(); settings.SslSettings.ClientCertificates = [clientCertificate]; AssertAuthenticationSucceeds(settings); @@ -64,7 +62,6 @@ public void Authentication_fails_with_MONGODB_X509_mechanism_when_username_is_wr var settings = DriverTestConfiguration.GetClientSettings().Clone(); settings.Credential = MongoCredential.CreateMongoX509Credential("wrong_username"); - settings.SslSettings = settings.SslSettings.Clone(); settings.SslSettings.ClientCertificates = [clientCertificate]; AssertAuthenticationFails(settings); @@ -82,8 +79,6 @@ public void Authentication_fails_with_MONGODB_X509_mechanism_when_user_is_not_in var clientCertificate = new X509Certificate2(pathToClientCertificate, password); var settings = DriverTestConfiguration.GetClientSettings().Clone(); - //settings.Credential = MongoCredential.CreateMongoX509Credential(); - settings.SslSettings = settings.SslSettings.Clone(); settings.SslSettings.ClientCertificates = [clientCertificate]; AssertAuthenticationFails(settings); From 7663f416ee6f95b9add32447b341b4677743c941 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 12:39:22 +0200 Subject: [PATCH 06/12] Simplified script handling --- evergreen/convert-client-cert-to-pkcs12.sh | 25 +++++++--------------- evergreen/run-tests.sh | 8 ++++--- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index 871071e243e..6f9a8a63d59 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -5,32 +5,23 @@ set -o errexit # Exit the script with an error if any of the commands fail # Input environment variables : "${CLIENT_PEM_VAR_NAME:="CLIENT_PEM"}" # Name of the input variable for the client.pem file : "${OUTPUT_VAR_PREFIX:="MONGO_X509_CLIENT"}" # Prefix for output environment variables -: "${CERTIFICATE_NAME:="Drivers Client Certificate"}" # Name for the exported certificate - -#todo, need to take the input name for client file and password, and not use the convoluted system we have -#I think I need to add those to the input environment variables and then use those in the export down here (where the default values for output variables are) +: "${FRIENDLY_NAME:="Drivers Client Certificate"}" # Friendly name for the exported certificate +: "${P12_FILENAME:="client.p12"}" +: "${P12_PASSWORD:="Picard-Alpha-Alpha-3-0-5"}" +: "${OUT_CLIENT_PASSWORD_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"}" +: "${OUT_CLIENT_PATH_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PATH"}" CLIENT_PEM=${!CLIENT_PEM_VAR_NAME:-nil} -OUT_CLIENT_P12_VAR="${OUTPUT_VAR_PREFIX}_CLIENT_P12" -OUT_CLIENT_PASSWORD_VAR="${OUTPUT_VAR_PREFIX}_CERTIFICATE_PASSWORD" -OUT_CLIENT_PATH_VAR="${OUTPUT_VAR_PREFIX}_CERTIFICATE_PATH" - -# Default values for output variables (can be overridden via the environment) -export "${OUT_CLIENT_P12_VAR}"="${!OUT_CLIENT_P12_VAR:-client.p12}" -export "${OUT_CLIENT_PASSWORD_VAR}"="${!OUT_CLIENT_PASSWORD_VAR:-Picard-Alpha-Alpha-3-0-5}" if [[ "$CLIENT_PEM" == "nil" ]]; then echo "Error: ${CLIENT_PEM_VAR_NAME} must be set." exit 1 fi -P12_FILENAME=${!OUT_CLIENT_P12_VAR} -CERT_PASSWORD=${!OUT_CLIENT_PASSWORD_VAR} - openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "${CLIENT_PEM}" \ -out "${P12_FILENAME}" \ - -name "${CERTIFICATE_NAME}" \ - -password "pass:${CERT_PASSWORD}" + -name "${FRIENDLY_NAME}" \ + -password "pass:${P12_PASSWORD}" # Determine path using realpath (compatible across macOS, Linux, and Windows) if [[ "$OS" =~ MAC|Mac|mac ]]; then @@ -55,9 +46,9 @@ if [[ "$OS" =~ Windows|windows ]]; then CERT_PATH=$(cygpath -w "${CERT_PATH}") fi +export "${OUT_CLIENT_PASSWORD_VAR}"="${P12_PASSWORD}" export "${OUT_CLIENT_PATH_VAR}"="${CERT_PATH}" echo "Exported variables:" -echo "${OUT_CLIENT_P12_VAR}=${!OUT_CLIENT_P12_VAR}" echo "${OUT_CLIENT_PASSWORD_VAR}=${!OUT_CLIENT_PASSWORD_VAR}" echo "${OUT_CLIENT_PATH_VAR}=${!OUT_CLIENT_PATH_VAR}" \ No newline at end of file diff --git a/evergreen/run-tests.sh b/evergreen/run-tests.sh index ce49752642e..73904e14a6e 100755 --- a/evergreen/run-tests.sh +++ b/evergreen/run-tests.sh @@ -134,11 +134,13 @@ if [[ "$CLIENT_PEM" != "nil" ]]; then CLIENT_PEM=${CLIENT_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi +#TODO need to remove this from here if [[ "$CLIENT_NO_USER_PEM" != "nil" ]]; then export CLIENT_PEM_VAR_NAME="CLIENT_NO_USER_PEM" - export OUTPUT_VAR_PREFIX="MONGO_X509_CLIENT_NO_USER" - export CERTIFICATE_NAME="Drivers No-User Client Certificate" - export MONGO_X509_CLIENT_NO_USER_CLIENT_P12="client_no_user.p12" + export FRIENDLY_NAME="Drivers No-User Client Certificate" + export P12_FILENAME="client_no_user.p12" + export OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" + export OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi From 992058f50c314d0514ad358e7ed3a75d43a3a70c Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 13:40:56 +0200 Subject: [PATCH 07/12] Corrections to scripts --- evergreen/evergreen.yml | 8 +++++++- evergreen/run-tests.sh | 11 ----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/evergreen/evergreen.yml b/evergreen/evergreen.yml index 3f67e388830..b77c90d37f0 100644 --- a/evergreen/evergreen.yml +++ b/evergreen/evergreen.yml @@ -386,9 +386,15 @@ functions: ${PREPARE_SHELL} OS=${OS} \ evergreen/add-ca-certs.sh + CLIENT_PEM_VAR_NAME="CLIENT_NO_USER_PEM" \ + FRIENDLY_NAME="Drivers No-User Client Certificate" \ + P12_FILENAME="client_no_user.p12" \ + OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \ + OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \ + CLIENT_NO_USER_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \ + source evergreen/convert-client-cert-to-pkcs12.sh MONGODB_URI="$ATLAS_X509_DEV" \ CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \ - CLIENT_NO_USER_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \ TOPOLOGY=${TOPOLOGY} \ OS=${OS} \ FRAMEWORK=${FRAMEWORK} \ diff --git a/evergreen/run-tests.sh b/evergreen/run-tests.sh index 73904e14a6e..6ec9620ff3b 100755 --- a/evergreen/run-tests.sh +++ b/evergreen/run-tests.sh @@ -29,7 +29,6 @@ TOPOLOGY=${TOPOLOGY:-server} COMPRESSOR=${COMPRESSOR:-none} OCSP_TLS_SHOULD_SUCCEED=${OCSP_TLS_SHOULD_SUCCEED:-nil} CLIENT_PEM=${CLIENT_PEM:-nil} -CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM:-nil} PLATFORM=${PLATFORM:-nil} TARGET=${TARGET:-Test} FRAMEWORK=${FRAMEWORK:-nil} @@ -134,16 +133,6 @@ if [[ "$CLIENT_PEM" != "nil" ]]; then CLIENT_PEM=${CLIENT_PEM} source evergreen/convert-client-cert-to-pkcs12.sh fi -#TODO need to remove this from here -if [[ "$CLIENT_NO_USER_PEM" != "nil" ]]; then - export CLIENT_PEM_VAR_NAME="CLIENT_NO_USER_PEM" - export FRIENDLY_NAME="Drivers No-User Client Certificate" - export P12_FILENAME="client_no_user.p12" - export OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" - export OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" - CLIENT_NO_USER_PEM=${CLIENT_NO_USER_PEM} source evergreen/convert-client-cert-to-pkcs12.sh -fi - if [[ -z "$MONGO_X509_CLIENT_CERTIFICATE_PATH" && -z "$MONGO_X509_CLIENT_CERTIFICATE_PASSWORD" ]]; then # technically the above condiion will be always true since CLIENT_PEM is always set and # convert-client-cert-to-pkcs12 always assigns these env variables, but leaving this condition in case From 41a83ee7671c812e38a58ac75944b15c3c8e573e Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:25:59 +0200 Subject: [PATCH 08/12] Various corrections and simplifications --- build.cake | 2 + evergreen/convert-client-cert-to-pkcs12.sh | 27 ++++-- evergreen/evergreen.yml | 96 +++++++++++----------- 3 files changed, 69 insertions(+), 56 deletions(-) diff --git a/build.cake b/build.cake index 17440fe000a..2ad45206ef6 100644 --- a/build.cake +++ b/build.cake @@ -261,6 +261,8 @@ Task("TestX509") action: (BuildConfig buildConfig, Path testProject) => RunTests(buildConfig, testProject, filter: "Category=\"X509\"")); +Task("TestX509Net60").IsDependentOn("TestX509"); + Task("Package") .IsDependentOn("PackageNugetPackages"); diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index 6f9a8a63d59..111f6468bca 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -2,19 +2,29 @@ set -o errexit # Exit the script with an error if any of the commands fail -# Input environment variables -: "${CLIENT_PEM_VAR_NAME:="CLIENT_PEM"}" # Name of the input variable for the client.pem file -: "${OUTPUT_VAR_PREFIX:="MONGO_X509_CLIENT"}" # Prefix for output environment variables -: "${FRIENDLY_NAME:="Drivers Client Certificate"}" # Friendly name for the exported certificate +# Environment variables used as input: +# CLIENT_PEM Path to mongo client.pem: must be set +# P12_FILENAME Filename for client certificate in p12 format +# P12_PASSWORD Password for client certificate in p12 format +# FRIENDLY_NAME Friendly name for client certificate in p12 format +# OUT_CLIENT_PATH_VAR Name of the output variable containing the path of the p12 certificate +# OUT_CLIENT_PASSWORD_VAR Name of the output variable containing the password for the p12 certificate +# +# Environment variables produced as output: +# {!OUT_CLIENT_PATH_VAR} Absolute path to client certificate in p12 format (OUT_CLIENT_PATH_VAR contains the actual variable being exported) +# {!OUT_CLIENT_PASSWORD_VAR} Password for client certificate (OUT_CLIENT_PASSWORD_VAR contains the actual variable being exported) + + +# Input environment variables and default values +: "${CLIENT_PEM:=nil}" +: "${FRIENDLY_NAME:="Drivers Client Certificate"}" : "${P12_FILENAME:="client.p12"}" : "${P12_PASSWORD:="Picard-Alpha-Alpha-3-0-5"}" -: "${OUT_CLIENT_PASSWORD_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"}" : "${OUT_CLIENT_PATH_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PATH"}" - -CLIENT_PEM=${!CLIENT_PEM_VAR_NAME:-nil} +: "${OUT_CLIENT_PASSWORD_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"}" if [[ "$CLIENT_PEM" == "nil" ]]; then - echo "Error: ${CLIENT_PEM_VAR_NAME} must be set." + echo "Error: CLIENT_PEM must be set." exit 1 fi @@ -46,6 +56,7 @@ if [[ "$OS" =~ Windows|windows ]]; then CERT_PATH=$(cygpath -w "${CERT_PATH}") fi +# Output environment variables export "${OUT_CLIENT_PASSWORD_VAR}"="${P12_PASSWORD}" export "${OUT_CLIENT_PATH_VAR}"="${CERT_PATH}" diff --git a/evergreen/evergreen.yml b/evergreen/evergreen.yml index b77c90d37f0..0aadb6dac4c 100644 --- a/evergreen/evergreen.yml +++ b/evergreen/evergreen.yml @@ -359,48 +359,6 @@ functions: cd ${DRIVERS_TOOLS}/.evergreen DRIVERS_TOOLS=${DRIVERS_TOOLS} MONGODB_URI=${MONGODB_URI} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh stop - - setup-x509-tests: - - command: shell.exec - params: - shell: "bash" - include_expansions_in_env: - - "AWS_ACCESS_KEY_ID" - - "AWS_SECRET_ACCESS_KEY" - - "AWS_SESSION_TOKEN" - script: | - ${DRIVERS_TOOLS}/.evergreen/secrets_handling/setup-secrets.sh drivers/atlas_connect - source secrets-export.sh - - echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem - echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem - - run-x509-tests: - - command: shell.exec - type: test - params: - shell: "bash" - working_dir: mongo-csharp-driver - script: | - source ../secrets-export.sh - ${PREPARE_SHELL} - OS=${OS} \ - evergreen/add-ca-certs.sh - CLIENT_PEM_VAR_NAME="CLIENT_NO_USER_PEM" \ - FRIENDLY_NAME="Drivers No-User Client Certificate" \ - P12_FILENAME="client_no_user.p12" \ - OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \ - OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \ - CLIENT_NO_USER_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \ - source evergreen/convert-client-cert-to-pkcs12.sh - MONGODB_URI="$ATLAS_X509_DEV" \ - CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \ - TOPOLOGY=${TOPOLOGY} \ - OS=${OS} \ - FRAMEWORK=${FRAMEWORK} \ - TARGET="TestX509" \ - evergreen/run-tests.sh - run-unit-tests: - command: shell.exec type: test @@ -1071,6 +1029,46 @@ functions: bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/run-driver-test.sh bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/teardown-pod.sh + setup-x509-tests: + - command: shell.exec + params: + shell: "bash" + include_expansions_in_env: + - "AWS_ACCESS_KEY_ID" + - "AWS_SECRET_ACCESS_KEY" + - "AWS_SESSION_TOKEN" + script: | + ${DRIVERS_TOOLS}/.evergreen/secrets_handling/setup-secrets.sh drivers/atlas_connect + source secrets-export.sh + + echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem + echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem + + run-x509-tests: + - command: shell.exec + type: test + params: + shell: "bash" + working_dir: mongo-csharp-driver + script: | + source ../secrets-export.sh + ${PREPARE_SHELL} + OS=${OS} \ + evergreen/add-ca-certs.sh + FRIENDLY_NAME="Drivers No-User Client Certificate" \ + P12_FILENAME="client_no_user.p12" \ + OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \ + OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \ + CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \ + source evergreen/convert-client-cert-to-pkcs12.sh + MONGODB_URI="$ATLAS_X509_DEV" \ + CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \ + TOPOLOGY=${TOPOLOGY} \ + OS=${OS} \ + FRAMEWORK=${FRAMEWORK} \ + TARGET="TestX509" \ + evergreen/run-tests.sh + pre: - func: fetch-source - func: prepare-resources @@ -1261,12 +1259,6 @@ tasks: - func: run-aws-auth-test-with-aws-ECS-credentials - func: run-aws-auth-test-with-aws-web-identity-credentials - - name: x509-auth-tests - commands: - - func: assume-ec2-role - - func: setup-x509-tests - - func: run-x509-tests - - name: stable-api-tests-net472 commands: - func: setup-csfle-secrets @@ -1768,6 +1760,14 @@ tasks: ${PREPARE_SHELL} CRYPT_SHARED_LIB_PATH="${CRYPT_SHARED_LIB_PATH}" DRIVER_VERSION="${PACKAGE_VERSION}" MONGODB_VERSION="${VERSION}" bash ./evergreen/run-tests.sh + - name: x509-auth-tests + commands: + - func: assume-ec2-role + - func: setup-x509-tests + - func: run-x509-tests + vars: + FRAMEWORK: net60 + axes: - id: version display_name: MongoDB Version From 6636f653ada0cd66bc0a3a6c3ef8748b6b2985da Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 15:26:13 +0200 Subject: [PATCH 09/12] Simplified tests --- tests/MongoDB.Driver.Tests/X509Tests.cs | 82 ++++++++++++++++--------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/tests/MongoDB.Driver.Tests/X509Tests.cs b/tests/MongoDB.Driver.Tests/X509Tests.cs index 12d3124341e..9a17c7cf557 100644 --- a/tests/MongoDB.Driver.Tests/X509Tests.cs +++ b/tests/MongoDB.Driver.Tests/X509Tests.cs @@ -35,15 +35,9 @@ public class X509Tests [Fact] public void Authentication_succeeds_with_MONGODB_X509_mechanism() { - RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true); - RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); - RequireServer.Check().Tls(required: true); - - var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); - var password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); - var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + var clientCertificate = GetClientCertificate(CertificateType.MONGO_X509); - var settings = DriverTestConfiguration.GetClientSettings().Clone(); + var settings = DriverTestConfiguration.GetClientSettings(); settings.SslSettings.ClientCertificates = [clientCertificate]; AssertAuthenticationSucceeds(settings); @@ -52,15 +46,9 @@ public void Authentication_succeeds_with_MONGODB_X509_mechanism() [Fact] public void Authentication_fails_with_MONGODB_X509_mechanism_when_username_is_wrong() { - RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true); - RequireEnvironment.Check().EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); - RequireServer.Check().Tls(required: true); - - var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); - var password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); - var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + var clientCertificate = GetClientCertificate(CertificateType.MONGO_X509); - var settings = DriverTestConfiguration.GetClientSettings().Clone(); + var settings = DriverTestConfiguration.GetClientSettings(); settings.Credential = MongoCredential.CreateMongoX509Credential("wrong_username"); settings.SslSettings.ClientCertificates = [clientCertificate]; @@ -70,18 +58,12 @@ public void Authentication_fails_with_MONGODB_X509_mechanism_when_username_is_wr [Fact] public void Authentication_fails_with_MONGODB_X509_mechanism_when_user_is_not_in_database() { - RequireEnvironment.Check().EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH, isDefined: true); - RequireEnvironment.Check().EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD, isDefined: true); - RequireServer.Check().Tls(required: true); - - var pathToClientCertificate = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH); - var password = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD); - var clientCertificate = new X509Certificate2(pathToClientCertificate, password); + var noUserClientCertificate = GetClientCertificate(CertificateType.MONGO_X509_CLIENT_NO_USER); - var settings = DriverTestConfiguration.GetClientSettings().Clone(); - settings.SslSettings.ClientCertificates = [clientCertificate]; + var settings = DriverTestConfiguration.GetClientSettings(); + settings.SslSettings.ClientCertificates = [noUserClientCertificate]; - AssertAuthenticationFails(settings); + AssertAuthenticationFails(settings, "Could not find user"); } private void AssertAuthenticationSucceeds(MongoClientSettings settings) @@ -90,14 +72,54 @@ private void AssertAuthenticationSucceeds(MongoClientSettings settings) _ = client.ListDatabaseNames().ToList(); } - private void AssertAuthenticationFails(MongoClientSettings settings) + private void AssertAuthenticationFails(MongoClientSettings settings, string innerExceptionMessage = null) { using var client = DriverTestConfiguration.CreateMongoClient(settings); var exception = Record.Exception(() => client.ListDatabaseNames().ToList()); exception.Should().BeOfType(); - // var innerException = exception.InnerException; - // innerException.Should().BeOfType(); - // innerException.Message.Should().Contain("Could not find user"); + if (innerExceptionMessage != null) + { + var innerException = exception.InnerException; + innerException.Should().BeOfType(); + innerException.Message.Should().Contain(innerExceptionMessage); + } + } + + private enum CertificateType + { + MONGO_X509, + MONGO_X509_CLIENT_NO_USER + } + + private X509Certificate2 GetClientCertificate(CertificateType certificateType) + { + RequireServer.Check().Tls(required: true); + + string path, password; + + switch (certificateType) + { + case CertificateType.MONGO_X509: + RequireEnvironment.Check() + .EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true) + .EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); + + path = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); + password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); + break; + case CertificateType.MONGO_X509_CLIENT_NO_USER: + RequireEnvironment.Check() + .EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH, isDefined: true) + .EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD, isDefined: true); + + path = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH); + password = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD); + break; + default: + throw new ArgumentException("Wrong certificate type specified.", nameof(certificateType)); + } + + return new X509Certificate2(path, password); } } \ No newline at end of file From 951c098a68376e523eeaa4f10aaf8a95e067c129 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:24:18 +0200 Subject: [PATCH 10/12] Small renaming --- evergreen/convert-client-cert-to-pkcs12.sh | 6 +++--- evergreen/evergreen.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index 111f6468bca..c828c2579e3 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -6,7 +6,7 @@ set -o errexit # Exit the script with an error if any of the commands fail # CLIENT_PEM Path to mongo client.pem: must be set # P12_FILENAME Filename for client certificate in p12 format # P12_PASSWORD Password for client certificate in p12 format -# FRIENDLY_NAME Friendly name for client certificate in p12 format +# P12_FRIENDLY_NAME Friendly name for client certificate in p12 format # OUT_CLIENT_PATH_VAR Name of the output variable containing the path of the p12 certificate # OUT_CLIENT_PASSWORD_VAR Name of the output variable containing the password for the p12 certificate # @@ -17,7 +17,7 @@ set -o errexit # Exit the script with an error if any of the commands fail # Input environment variables and default values : "${CLIENT_PEM:=nil}" -: "${FRIENDLY_NAME:="Drivers Client Certificate"}" +: "${P12_FRIENDLY_NAME:="Drivers Client Certificate"}" : "${P12_FILENAME:="client.p12"}" : "${P12_PASSWORD:="Picard-Alpha-Alpha-3-0-5"}" : "${OUT_CLIENT_PATH_VAR:="MONGO_X509_CLIENT_CERTIFICATE_PATH"}" @@ -30,7 +30,7 @@ fi openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -in "${CLIENT_PEM}" \ -out "${P12_FILENAME}" \ - -name "${FRIENDLY_NAME}" \ + -name "${P12_FRIENDLY_NAME}" \ -password "pass:${P12_PASSWORD}" # Determine path using realpath (compatible across macOS, Linux, and Windows) diff --git a/evergreen/evergreen.yml b/evergreen/evergreen.yml index 0aadb6dac4c..bf9dbbff883 100644 --- a/evergreen/evergreen.yml +++ b/evergreen/evergreen.yml @@ -1055,7 +1055,7 @@ functions: ${PREPARE_SHELL} OS=${OS} \ evergreen/add-ca-certs.sh - FRIENDLY_NAME="Drivers No-User Client Certificate" \ + P12_FRIENDLY_NAME="Drivers No-User Client Certificate" \ P12_FILENAME="client_no_user.p12" \ OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \ OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \ From cd26e7ddf6c9b1ceefb7270e94e52e71c81486e8 Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Mon, 18 Aug 2025 17:37:31 +0200 Subject: [PATCH 11/12] Corrected spacing --- evergreen/convert-client-cert-to-pkcs12.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evergreen/convert-client-cert-to-pkcs12.sh b/evergreen/convert-client-cert-to-pkcs12.sh index c828c2579e3..b5523c86d49 100755 --- a/evergreen/convert-client-cert-to-pkcs12.sh +++ b/evergreen/convert-client-cert-to-pkcs12.sh @@ -6,13 +6,13 @@ set -o errexit # Exit the script with an error if any of the commands fail # CLIENT_PEM Path to mongo client.pem: must be set # P12_FILENAME Filename for client certificate in p12 format # P12_PASSWORD Password for client certificate in p12 format -# P12_FRIENDLY_NAME Friendly name for client certificate in p12 format +# P12_FRIENDLY_NAME Friendly name for client certificate in p12 format # OUT_CLIENT_PATH_VAR Name of the output variable containing the path of the p12 certificate # OUT_CLIENT_PASSWORD_VAR Name of the output variable containing the password for the p12 certificate # # Environment variables produced as output: -# {!OUT_CLIENT_PATH_VAR} Absolute path to client certificate in p12 format (OUT_CLIENT_PATH_VAR contains the actual variable being exported) -# {!OUT_CLIENT_PASSWORD_VAR} Password for client certificate (OUT_CLIENT_PASSWORD_VAR contains the actual variable being exported) +# ${OUT_CLIENT_PATH_VAR} Absolute path to client certificate in p12 format (OUT_CLIENT_PATH_VAR contains the actual variable being exported) +# ${OUT_CLIENT_PASSWORD_VAR} Password for client certificate (OUT_CLIENT_PASSWORD_VAR contains the actual variable being exported) # Input environment variables and default values From 449d8289d2196c129a878ca41ad8d621ab3c5b9e Mon Sep 17 00:00:00 2001 From: Ferdinando Papale <4850119+papafe@users.noreply.github.com> Date: Tue, 19 Aug 2025 09:39:53 +0200 Subject: [PATCH 12/12] Small fixes. --- tests/MongoDB.Driver.Tests/X509Tests.cs | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/MongoDB.Driver.Tests/X509Tests.cs b/tests/MongoDB.Driver.Tests/X509Tests.cs index 9a17c7cf557..a948204ae6f 100644 --- a/tests/MongoDB.Driver.Tests/X509Tests.cs +++ b/tests/MongoDB.Driver.Tests/X509Tests.cs @@ -96,30 +96,30 @@ private X509Certificate2 GetClientCertificate(CertificateType certificateType) { RequireServer.Check().Tls(required: true); - string path, password; + string pathVariable = null; + string passwordVariable = null; switch (certificateType) { case CertificateType.MONGO_X509: - RequireEnvironment.Check() - .EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH, isDefined: true) - .EnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD, isDefined: true); - - path = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PATH); - password = Environment.GetEnvironmentVariable(MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD); + pathVariable = MONGODB_X509_CLIENT_CERTIFICATE_PATH; + passwordVariable = MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD; break; case CertificateType.MONGO_X509_CLIENT_NO_USER: - RequireEnvironment.Check() - .EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH, isDefined: true) - .EnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD, isDefined: true); - - path = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH); - password = Environment.GetEnvironmentVariable(MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD); + pathVariable = MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH; + passwordVariable = MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD; break; default: throw new ArgumentException("Wrong certificate type specified.", nameof(certificateType)); } + RequireEnvironment.Check() + .EnvironmentVariable(pathVariable, isDefined: true) + .EnvironmentVariable(passwordVariable, isDefined: true); + + var path = Environment.GetEnvironmentVariable(pathVariable); + var password = Environment.GetEnvironmentVariable(passwordVariable); + return new X509Certificate2(path, password); } } \ No newline at end of file