Skip to content

Commit 3669ba7

Browse files
authored
CSHARP-5581: Test MONGODB-X509 on cloud-dev (#1757)
1 parent 5ba7f77 commit 3669ba7

File tree

4 files changed

+219
-15
lines changed

4 files changed

+219
-15
lines changed

build.cake

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ Task("TestCsfleWithGcpKms")
254254
action: (BuildConfig buildConfig, Path testProject) =>
255255
RunTests(buildConfig, testProject, filter: "Category=\"CsfleGCPKMS\""));
256256

257+
Task("TestX509")
258+
.IsDependentOn("Build")
259+
.DoesForEach(
260+
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
261+
action: (BuildConfig buildConfig, Path testProject) =>
262+
RunTests(buildConfig, testProject, filter: "Category=\"X509\""));
263+
264+
Task("TestX509Net60").IsDependentOn("TestX509");
265+
257266
Task("Package")
258267
.IsDependentOn("PackageNugetPackages");
259268

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
@@ -1029,6 +1029,46 @@ functions:
10291029
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/run-driver-test.sh
10301030
bash $DRIVERS_TOOLS/.evergreen/auth_oidc/k8s/teardown-pod.sh
10311031
1032+
setup-x509-tests:
1033+
- command: shell.exec
1034+
params:
1035+
shell: "bash"
1036+
include_expansions_in_env:
1037+
- "AWS_ACCESS_KEY_ID"
1038+
- "AWS_SECRET_ACCESS_KEY"
1039+
- "AWS_SESSION_TOKEN"
1040+
script: |
1041+
${DRIVERS_TOOLS}/.evergreen/secrets_handling/setup-secrets.sh drivers/atlas_connect
1042+
source secrets-export.sh
1043+
1044+
echo $ATLAS_X509_DEV_CERT_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_CERT.pem
1045+
echo $ATLAS_X509_DEV_CERT_NOUSER_BASE64 | base64 --decode > ${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem
1046+
1047+
run-x509-tests:
1048+
- command: shell.exec
1049+
type: test
1050+
params:
1051+
shell: "bash"
1052+
working_dir: mongo-csharp-driver
1053+
script: |
1054+
source ../secrets-export.sh
1055+
${PREPARE_SHELL}
1056+
OS=${OS} \
1057+
evergreen/add-ca-certs.sh
1058+
P12_FRIENDLY_NAME="Drivers No-User Client Certificate" \
1059+
P12_FILENAME="client_no_user.p12" \
1060+
OUT_CLIENT_PASSWORD_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD" \
1061+
OUT_CLIENT_PATH_VAR="MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH" \
1062+
CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_NO_USER_CERT.pem \
1063+
source evergreen/convert-client-cert-to-pkcs12.sh
1064+
MONGODB_URI="$ATLAS_X509_DEV" \
1065+
CLIENT_PEM=${DRIVERS_TOOLS}/CLIENT_CERT.pem \
1066+
TOPOLOGY=${TOPOLOGY} \
1067+
OS=${OS} \
1068+
FRAMEWORK=${FRAMEWORK} \
1069+
TARGET="TestX509" \
1070+
evergreen/run-tests.sh
1071+
10321072
pre:
10331073
- func: fetch-source
10341074
- func: prepare-resources
@@ -1720,6 +1760,14 @@ tasks:
17201760
${PREPARE_SHELL}
17211761
CRYPT_SHARED_LIB_PATH="${CRYPT_SHARED_LIB_PATH}" DRIVER_VERSION="${PACKAGE_VERSION}" MONGODB_VERSION="${VERSION}" bash ./evergreen/run-tests.sh
17221762
1763+
- name: x509-auth-tests
1764+
commands:
1765+
- func: assume-ec2-role
1766+
- func: setup-x509-tests
1767+
- func: run-x509-tests
1768+
vars:
1769+
FRAMEWORK: net60
1770+
17231771
axes:
17241772
- id: version
17251773
display_name: MongoDB Version
@@ -2417,6 +2465,12 @@ buildvariants:
24172465
- name: test-gssapi-netstandard21
24182466
- name: test-gssapi-net60
24192467

2468+
- matrix_name: "x509-tests"
2469+
matrix_spec: { os: ["ubuntu-2004", "macos-14", "windows-64"], ssl: ["ssl"], version: ["latest"], topology: ["standalone"] }
2470+
display_name: "X509 tests ${version} ${os}"
2471+
tasks:
2472+
- name: x509-auth-tests
2473+
24202474
# Load balancer tests
24212475
- matrix_name: load-balancer-tests
24222476
matrix_spec: { version: ["5.0", "6.0", "7.0", "8.0", "rapid", "latest"], auth: "noauth", ssl: "nossl", topology: "sharded-cluster", os: "ubuntu-2004" }
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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.Security.Cryptography.X509Certificates;
18+
using FluentAssertions;
19+
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
20+
using MongoDB.TestHelpers.XunitExtensions;
21+
using Xunit;
22+
23+
namespace MongoDB.Driver.Tests;
24+
25+
[Trait("Category", "Integration")]
26+
[Trait("Category", "X509")]
27+
public class X509Tests
28+
{
29+
const string MONGODB_X509_CLIENT_CERTIFICATE_PATH = "MONGO_X509_CLIENT_CERTIFICATE_PATH";
30+
const string MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD = "MONGO_X509_CLIENT_CERTIFICATE_PASSWORD";
31+
32+
const string MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH = "MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH";
33+
const string MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD = "MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD";
34+
35+
[Fact]
36+
public void Authentication_succeeds_with_MONGODB_X509_mechanism()
37+
{
38+
var clientCertificate = GetClientCertificate(CertificateType.MONGO_X509);
39+
40+
var settings = DriverTestConfiguration.GetClientSettings();
41+
settings.SslSettings.ClientCertificates = [clientCertificate];
42+
43+
AssertAuthenticationSucceeds(settings);
44+
}
45+
46+
[Fact]
47+
public void Authentication_fails_with_MONGODB_X509_mechanism_when_username_is_wrong()
48+
{
49+
var clientCertificate = GetClientCertificate(CertificateType.MONGO_X509);
50+
51+
var settings = DriverTestConfiguration.GetClientSettings();
52+
settings.Credential = MongoCredential.CreateMongoX509Credential("wrong_username");
53+
settings.SslSettings.ClientCertificates = [clientCertificate];
54+
55+
AssertAuthenticationFails(settings);
56+
}
57+
58+
[Fact]
59+
public void Authentication_fails_with_MONGODB_X509_mechanism_when_user_is_not_in_database()
60+
{
61+
var noUserClientCertificate = GetClientCertificate(CertificateType.MONGO_X509_CLIENT_NO_USER);
62+
63+
var settings = DriverTestConfiguration.GetClientSettings();
64+
settings.SslSettings.ClientCertificates = [noUserClientCertificate];
65+
66+
AssertAuthenticationFails(settings, "Could not find user");
67+
}
68+
69+
private void AssertAuthenticationSucceeds(MongoClientSettings settings)
70+
{
71+
using var client = DriverTestConfiguration.CreateMongoClient(settings);
72+
_ = client.ListDatabaseNames().ToList();
73+
}
74+
75+
private void AssertAuthenticationFails(MongoClientSettings settings, string innerExceptionMessage = null)
76+
{
77+
using var client = DriverTestConfiguration.CreateMongoClient(settings);
78+
var exception = Record.Exception(() => client.ListDatabaseNames().ToList());
79+
exception.Should().BeOfType<MongoAuthenticationException>();
80+
81+
if (innerExceptionMessage != null)
82+
{
83+
var innerException = exception.InnerException;
84+
innerException.Should().BeOfType<MongoCommandException>();
85+
innerException.Message.Should().Contain(innerExceptionMessage);
86+
}
87+
}
88+
89+
private enum CertificateType
90+
{
91+
MONGO_X509,
92+
MONGO_X509_CLIENT_NO_USER
93+
}
94+
95+
private X509Certificate2 GetClientCertificate(CertificateType certificateType)
96+
{
97+
RequireServer.Check().Tls(required: true);
98+
99+
string pathVariable = null;
100+
string passwordVariable = null;
101+
102+
switch (certificateType)
103+
{
104+
case CertificateType.MONGO_X509:
105+
pathVariable = MONGODB_X509_CLIENT_CERTIFICATE_PATH;
106+
passwordVariable = MONGODB_X509_CLIENT_CERTIFICATE_PASSWORD;
107+
break;
108+
case CertificateType.MONGO_X509_CLIENT_NO_USER:
109+
pathVariable = MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PATH;
110+
passwordVariable = MONGO_X509_CLIENT_NO_USER_CERTIFICATE_PASSWORD;
111+
break;
112+
default:
113+
throw new ArgumentException("Wrong certificate type specified.", nameof(certificateType));
114+
}
115+
116+
RequireEnvironment.Check()
117+
.EnvironmentVariable(pathVariable, isDefined: true)
118+
.EnvironmentVariable(passwordVariable, isDefined: true);
119+
120+
var path = Environment.GetEnvironmentVariable(pathVariable);
121+
var password = Environment.GetEnvironmentVariable(passwordVariable);
122+
123+
return new X509Certificate2(path, password);
124+
}
125+
}

0 commit comments

Comments
 (0)