Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PYTHON-2608 Test that KMS TLS connections verify peer certificates #667

Merged
merged 17 commits into from Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 11 additions & 11 deletions .evergreen/config.yml
Expand Up @@ -292,7 +292,7 @@ functions:
DISABLE_TEST_COMMANDS=${DISABLE_TEST_COMMANDS} \
ORCHESTRATION_FILE=${ORCHESTRATION_FILE} \
REQUIRE_API_VERSION=${REQUIRE_API_VERSION} \
sh ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh
bash ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh
# run-orchestration generates expansion file with the MONGODB_URI for the cluster
- command: expansions.update
params:
Expand All @@ -310,23 +310,23 @@ functions:
script: |
set -o xtrace
${PREPARE_SHELL}
sh ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/build-mongohouse-local.sh
bash ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/build-mongohouse-local.sh
- command: shell.exec
type: setup
params:
background: true
script: |
set -o xtrace
${PREPARE_SHELL}
sh ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/run-mongohouse-local.sh
bash ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/run-mongohouse-local.sh

"stop mongo-orchestration":
- command: shell.exec
params:
script: |
set -o xtrace
${PREPARE_SHELL}
sh ${DRIVERS_TOOLS}/.evergreen/stop-orchestration.sh
bash ${DRIVERS_TOOLS}/.evergreen/stop-orchestration.sh

"run mod_wsgi tests":
- command: shell.exec
Expand All @@ -336,7 +336,7 @@ functions:
script: |
set -o xtrace
${PREPARE_SHELL}
PYTHON_BINARY=${PYTHON_BINARY} MOD_WSGI_VERSION=${MOD_WSGI_VERSION} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} sh ${PROJECT_DIRECTORY}/.evergreen/run-mod-wsgi-tests.sh
PYTHON_BINARY=${PYTHON_BINARY} MOD_WSGI_VERSION=${MOD_WSGI_VERSION} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} bash ${PROJECT_DIRECTORY}/.evergreen/run-mod-wsgi-tests.sh

"run mockupdb tests":
- command: shell.exec
Expand All @@ -346,7 +346,7 @@ functions:
script: |
set -o xtrace
${PREPARE_SHELL}
PYTHON_BINARY=${PYTHON_BINARY} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} sh ${PROJECT_DIRECTORY}/.evergreen/run-mockupdb-tests.sh
PYTHON_BINARY=${PYTHON_BINARY} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} bash ${PROJECT_DIRECTORY}/.evergreen/run-mockupdb-tests.sh

"run doctests":
- command: shell.exec
Expand All @@ -356,7 +356,7 @@ functions:
script: |
set -o xtrace
${PREPARE_SHELL}
PYTHON_BINARY=${PYTHON_BINARY} sh ${PROJECT_DIRECTORY}/.evergreen/run-doctests.sh
PYTHON_BINARY=${PYTHON_BINARY} bash ${PROJECT_DIRECTORY}/.evergreen/run-doctests.sh

"run tests":
- command: shell.exec
Expand Down Expand Up @@ -425,7 +425,7 @@ functions:
SSL=${SSL} \
DATA_LAKE=${DATA_LAKE} \
MONGODB_API_VERSION=${MONGODB_API_VERSION} \
sh ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh
bash ${PROJECT_DIRECTORY}/.evergreen/run-tests.sh

"run enterprise auth tests":
- command: shell.exec
Expand All @@ -435,7 +435,7 @@ functions:
working_dir: "src"
script: |
# DO NOT ECHO WITH XTRACE (which PREPARE_SHELL does)
PYTHON_BINARY=${PYTHON_BINARY} SASL_HOST=${sasl_host} SASL_PORT=${sasl_port} SASL_USER=${sasl_user} SASL_PASS=${sasl_pass} SASL_DB=${sasl_db} PRINCIPAL=${principal} GSSAPI_DB=${gssapi_db} KEYTAB_BASE64=${keytab_base64} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} sh ${PROJECT_DIRECTORY}/.evergreen/run-enterprise-auth-tests.sh
PYTHON_BINARY=${PYTHON_BINARY} SASL_HOST=${sasl_host} SASL_PORT=${sasl_port} SASL_USER=${sasl_user} SASL_PASS=${sasl_pass} SASL_DB=${sasl_db} PRINCIPAL=${principal} GSSAPI_DB=${gssapi_db} KEYTAB_BASE64=${keytab_base64} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} bash ${PROJECT_DIRECTORY}/.evergreen/run-enterprise-auth-tests.sh

"run atlas tests":
- command: shell.exec
Expand Down Expand Up @@ -705,7 +705,7 @@ functions:
${PREPARE_SHELL}
file="${PROJECT_DIRECTORY}/.evergreen/install-dependencies.sh"
# Don't use ${file} syntax here because evergreen treats it as an empty expansion.
[ -f "$file" ] && sh $file || echo "$file not available, skipping"
[ -f "$file" ] && bash $file || echo "$file not available, skipping"

"run-ocsp-test":
- command: shell.exec
Expand All @@ -717,7 +717,7 @@ functions:
PYTHON_BINARY=${PYTHON_BINARY} \
CA_FILE="$DRIVERS_TOOLS/.evergreen/ocsp/${OCSP_ALGORITHM}/ca.pem" \
OCSP_TLS_SHOULD_SUCCEED="${OCSP_TLS_SHOULD_SUCCEED}" \
sh ${PROJECT_DIRECTORY}/.evergreen/run-ocsp-tests.sh
bash ${PROJECT_DIRECTORY}/.evergreen/run-ocsp-tests.sh

run-valid-ocsp-server:
- command: shell.exec
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/install-dependencies.sh
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
set -o xtrace # Write all commands first to stderr
set -o errexit # Exit the script with error if any of the commands fail

Expand Down
2 changes: 1 addition & 1 deletion .evergreen/run-mod-wsgi-tests.sh
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
set -o xtrace
set -o errexit

Expand Down
9 changes: 9 additions & 0 deletions .evergreen/run-tests.sh
Expand Up @@ -144,6 +144,15 @@ if [ -n "$TEST_ENCRYPTION" ]; then
# Get access to the AWS temporary credentials:
# CSFLE_AWS_TEMP_ACCESS_KEY_ID, CSFLE_AWS_TEMP_SECRET_ACCESS_KEY, CSFLE_AWS_TEMP_SESSION_TOKEN
. $DRIVERS_TOOLS/.evergreen/csfle/set-temp-creds.sh

# Start the mock KMS servers.
if [ "$OS" != "Windows_NT" ]; then
pushd ${DRIVERS_TOOLS}/.evergreen/csfle
python -u lib/kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/expired.pem --port 8000 &
python -u lib/kms_http_server.py --ca_file ../x509gen/ca.pem --cert_file ../x509gen/wrong-host.pem --port 8001 &
trap 'kill $(jobs -p)' EXIT HUP
popd
fi
fi

if [ -z "$DATA_LAKE" ]; then
Expand Down
57 changes: 57 additions & 0 deletions test/test_encryption.py
Expand Up @@ -19,6 +19,7 @@
import os
import traceback
import socket
import ssl
import sys
import textwrap
import uuid
Expand Down Expand Up @@ -49,6 +50,7 @@
WriteError)
from pymongo.mongo_client import MongoClient
from pymongo.operations import InsertOne
from pymongo.ssl_support import _ssl
from pymongo.write_concern import WriteConcern

from test import unittest, IntegrationTest, PyMongoTestCase, client_context
Expand All @@ -60,6 +62,7 @@
rs_or_single_client,
wait_until)
from test.utils_spec_runner import SpecRunner
from test.test_ssl import CA_PEM


def get_client_opts(client):
Expand Down Expand Up @@ -1624,5 +1627,59 @@ def test_bypassAutoEncryption(self):
mongocryptd_client.admin.command('ping')


# https://github.com/mongodb/specifications/tree/master/source/client-side-encryption/tests#kms-tls-tests
class TestKmsTLSProse(EncryptionIntegrationTest):
@unittest.skipIf(sys.platform == 'win32',
"Can't test system ca certs on Windows")
@unittest.skipIf(ssl.OPENSSL_VERSION.lower().startswith('libressl') and
sys.platform == 'darwin' and not _ssl.IS_PYOPENSSL,
"LibreSSL on OSX doesn't support setting CA certificates "
"using SSL_CERT_FILE environment variable.")
@unittest.skipUnless(any(AWS_CREDS.values()),
'AWS environment credentials are not set')
def setUp(self):
self.original_certs = os.environ.get('SSL_CERT_FILE')
def restore_certs():
if self.original_certs is None:
os.environ.pop('SSL_CERT_FILE')
else:
os.environ['SSL_CERT_FILE'] = self.original_certs
# Tell OpenSSL where CA certificates live.
os.environ['SSL_CERT_FILE'] = CA_PEM
self.addCleanup(restore_certs)

self.client_encrypted = ClientEncryption(
{'aws': AWS_CREDS}, 'keyvault.datakeys', self.client, OPTS)
self.addCleanup(self.client_encrypted.close)

def test_invalid_kms_certificate_expired(self):
key = {
"region": "us-east-1",
"key": "arn:aws:kms:us-east-1:579766882180:key/"
"89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
"endpoint": "mongodb://127.0.0.1:8000",
}
# Some examples:
# certificate verify failed: certificate has expired (_ssl.c:1129)
# amazon1-2018 Python 3.6: certificate verify failed (_ssl.c:852)
with self.assertRaisesRegex(
EncryptionError, 'expired|certificate verify failed'):
self.client_encrypted.create_data_key('aws', master_key=key)

def test_invalid_hostname_in_kms_certificate(self):
key = {
"region": "us-east-1",
"key": "arn:aws:kms:us-east-1:579766882180:key/"
"89fcc2c4-08b0-4bd9-9f25-e30687b580d0",
"endpoint": "mongodb://127.0.0.1:8001",
}
# Some examples:
# certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'. (_ssl.c:1129)"
# hostname '127.0.0.1' doesn't match 'wronghost.com'
with self.assertRaisesRegex(
EncryptionError, 'IP address mismatch|wronghost'):
self.client_encrypted.create_data_key('aws', master_key=key)


if __name__ == "__main__":
unittest.main()