0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 17:10:48 +01:00

SERVER-36618 Write JS integration tests that validate whichever TLS suites are available on each Evergreen platform

This commit is contained in:
Shreyas Kalyan 2018-09-25 16:15:24 -04:00
parent 82a07e2f04
commit 0169d181bd
6 changed files with 168 additions and 5 deletions

View File

@ -7014,6 +7014,20 @@ tasks:
name: ssl
commands:
- func: "do setup"
- command: shell.exec
type: test
params:
working_dir: src
script: |
set -o errexit
set -o verbose
${activate_virtualenv}
if [ "Windows_NT" = "$OS" ]; then
/cygdrive/c/python/python36/python.exe -m pip install -r etc/pip/evgtest-requirements.txt
else
python3 -m pip install -r etc/pip/evgtest-requirements.txt
fi
- func: "run tests"
vars:
resmoke_args: --suites=ssl --storageEngine=wiredTiger

View File

@ -2,5 +2,5 @@
jira
requests-oauth
PyJWT # https://github.com/pycontribs/jira/issues/247
cryptography # Needed for oauthlib to use RSAAlgorithm
cryptography == 2.3 # Needed for oauthlib to use RSAAlgorithm # Version locked - see SERVER-36618
# We are omitting pycrypto based on https://github.com/pycontribs/jira/pull/629

View File

@ -2,3 +2,5 @@
pypiwin32==219; sys_platform == "win32" and python_version < "3"
pypiwin32==223; sys_platform == "win32" and python_version > "3"
subprocess32==3.5.2; os_name == "posix" and platform_release != "2.6.18-194.el5xen" and platform_release != "2.6.18-274.el5xen" and python_version < "3"
# Needed for ssl_ECDHE_suites.js test - testing the TLS suites enabled on each platform
sslyze==2.0.1; python_version >= "3.6" and sys_platform != "darwin"

View File

@ -6,12 +6,12 @@
# Common requirements
asn1crypto==0.24.0
boto3==1.9.14
botocore==1.12.14
boto3==1.9.16
botocore==1.12.16
certifi==2018.8.24
cffi==1.11.5
chardet==3.0.4
cryptography==2.3.1
cryptography==2.3
defusedxml==0.5.0
docutils==0.14
idna==2.7
@ -23,7 +23,7 @@ lazy-object-proxy==1.3.1
MarkupSafe==1.0
mccabe==0.6.1
oauthlib==2.1.0
pbr==4.2.0
pbr==4.3.0
psutil==5.4.7
pycparser==2.19
pydocstyle==2.1.1
@ -68,3 +68,5 @@ typed-ast==1.1.0; python_version > "3"
pypiwin32==219; sys_platform == "win32" and python_version < "3"
pypiwin32==223; sys_platform == "win32" and python_version > "3"
subprocess32==3.5.2; os_name == "posix" and platform_release != "2.6.18-194.el5xen" and platform_release != "2.6.18-274.el5xen" and python_version < "3"
# Needed for ssl_ECDHE_suites.js test - testing the TLS suites enabled on each platform
sslyze==2.0.1; python_version >= "3.6" and sys_platform != "darwin"

View File

@ -0,0 +1,93 @@
// Test that a client can authenicate against the server with roles.
// Also validates RFC2253
load('jstests/ssl/libs/ssl_helpers.js');
(function() {
"use strict";
if (getBuildInfo().buildEnvironment.target_os === "macOS") {
return;
}
const suites = [
"SSLV2 Cipher Suites",
"SSLV3 Cipher Suites",
"TLSV1_0 Cipher Suites",
"TLSV1_1 Cipher Suites",
"TLSV1_2 Cipher Suites",
"TLSV1_3 Cipher Suites"
];
const SERVER_CERT = "jstests/libs/server.pem";
function runSSLYze(port) {
let python = "/usr/bin/env python3";
let sslyze = " jstests/ssl/sslyze_tester.py ";
if (_isWindows()) {
const paths = ["c:\\python36\\python.exe", "c:\\python\\python36\\python.exe"];
for (let p of paths) {
if (fileExists(p)) {
python = p;
}
}
}
const python_command = python + sslyze + "--port=" + port;
let ret = 0;
if (_isWindows()) {
ret = runProgram('cmd.exe', '/c', python_command);
} else {
ret = runProgram('/bin/sh', '-c', python_command);
}
assert.eq(ret, 0);
try {
let ciphers = cat("jstests/ssl/ciphers.json");
let cipherDict = JSON.parse(ciphers);
return cipherDict;
} catch (e) {
jsTestLog("Failed to parse: " + ciphers + "\n" + ciphers);
throw e;
} finally {
const python_delete_command = python + sslyze + "--delete";
if (_isWindows()) {
ret = runProgram('cmd.exe', '/c', python_delete_command);
} else {
ret = runProgram('/bin/sh', '-c', python_delete_command);
}
assert.eq(ret, 0);
}
}
function testSSLYzeOutput(cipherDict) {
// Checking that SSL 1.0, 2.0, 3.0 and TLS 1.0 are not accepted
for (var i = 0; i < 3; i++) {
assert.eq(cipherDict[suites[i]].length, 0);
}
// Printing TLS 1.1, 1.2, and 1.3 suites that are accepted
for (var i = 3; i < 6; i++) {
const TLSVersion = cipherDict[suites[i]].toString().split(",");
print('*************************\n' + suites[i] + ": ");
for (var j = 0; j < TLSVersion.length; j++) {
print(TLSVersion[j]);
}
}
}
print("1. Testing x.509 auth to mongod");
{
const x509_options = {
sslMode: "requireSSL",
sslCAFile: CA_CERT,
sslPEMKeyFile: SERVER_CERT,
ipv6: "",
bind_ip_all: ""
};
let mongod = MongoRunner.runMongod(x509_options);
var cipherDict = runSSLYze(mongod.port);
testSSLYzeOutput(cipherDict);
MongoRunner.stopMongod(mongod);
}
}());

View File

@ -0,0 +1,52 @@
#! /usr/bin/env python3
# This is a wrapper file around the SSLYze package
# The SSLYze package is used for testing the TLS/SSL
# suites that we allow for connections.
import os, logging, json, argparse, urllib.parse
from sslyze.synchronous_scanner import SynchronousScanner
from sslyze.plugins import openssl_cipher_suites_plugin
from sslyze.plugins.openssl_cipher_suites_plugin import *
from sslyze.server_connectivity_tester import ServerConnectivityTester, ServerConnectivityError
path = str(os.path.dirname(os.path.abspath(__file__)))
filename = f'{path}/ciphers.json'
def server_scanner(p):
try:
logger = logging.getLogger(__name__)
logger.info("Opening file")
server_tester = ServerConnectivityTester(
hostname = 'localhost',
port=p
)
server_info = server_tester.perform()
scanner = SynchronousScanner()
results = dict()
suite_names = ['SSLV2 Cipher Suites', 'SSLV3 Cipher Suites', 'TLSV1_0 Cipher Suites', 'TLSV1_1 Cipher Suites', 'TLSV1_2 Cipher Suites', 'TLSV1_3 Cipher Suites']
suites = [Sslv20ScanCommand, Sslv30ScanCommand, Tlsv10ScanCommand, Tlsv11ScanCommand, Tlsv12ScanCommand, Tlsv13ScanCommand]
logger.info("Scanning SSL/TLS suites, writing to ciphers.json")
for suite_name, suite in zip(suite_names, suites):
scan = scanner.run_scan_command(server_info, suite())
results[suite_name] = [cipher.name for cipher in scan.accepted_cipher_list]
with open(filename, 'w') as outfile:
json.dump(results, outfile)
except ServerConnectivityError as e:
raise RuntimeError(f'Could not connect to {e.server_info.hostname}: {e.error_message}')
def main():
parser = argparse.ArgumentParser(description='MongoDB SSL/TLS Suite Validation.')
parser.add_argument('-p', '--port', type=int, default=27017, help="Port to listen on")
parser.add_argument('-d', '--delete', action='store_true', help="Delete the ciphers.json file")
args = parser.parse_args()
if args.delete:
os.remove(filename)
else:
return server_scanner(args.port)
if __name__ == '__main__':
main()