Also add verify_ssl argument

Without verify_ssl it's a bit complicated to test, and if someone wants
to use self-signed certs in their environment without actually
installing the certs or making a CA, that should also be up to them.
This commit is contained in:
Wayne Werner 2022-02-24 11:48:22 -06:00 committed by Daniel Wozniak
parent a3cf72005d
commit e086090e33
10 changed files with 524 additions and 72 deletions

View file

@ -52,6 +52,7 @@ def _connect(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Connect to a mongodb database with pymongo.MongoClient. If user and
@ -70,6 +71,7 @@ def _connect(
If connection fails for any reason, log error and return False.
"""
verify_ssl = True if verify_ssl is None else verify_ssl
if not user:
user = __salt__["config.option"]("mongodb.user")
if not password:
@ -82,11 +84,16 @@ def _connect(
authdb = database
try:
conn = pymongo.MongoClient(host=host, port=port, ssl=bool(ssl))
conn = pymongo.MongoClient(
host=host,
port=port,
ssl=bool(ssl),
tlsAllowInvalidCertificates=not verify_ssl,
)
mdb = pymongo.database.Database(conn, database)
if user and password:
mdb.authenticate(user, password, source=authdb)
except pymongo.errors.PyMongoError:
except pymongo.errors.PyMongoError as e:
log.error("Error connecting to database %s", database)
return False
@ -107,7 +114,15 @@ def _to_dict(objects):
return objects
def db_list(user=None, password=None, host=None, port=None, authdb=None, ssl=False):
def db_list(
user=None,
password=None,
host=None,
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
List all MongoDB databases.
@ -152,7 +167,9 @@ def db_list(user=None, password=None, host=None, port=None, authdb=None, ssl=Fal
salt '*' mongodb.db_list <user> <password> <host> <port>
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -160,12 +177,20 @@ def db_list(user=None, password=None, host=None, port=None, authdb=None, ssl=Fal
log.info("Listing databases")
return conn.list_database_names()
except pymongo.errors.PyMongoError as err:
print("Ooops")
log.error(err)
return str(err)
def db_exists(
name, user=None, password=None, host=None, port=None, authdb=None, ssl=False
name,
user=None,
password=None,
host=None,
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Checks if a database exists in MongoDB.
@ -217,7 +242,9 @@ def db_exists(
salt '*' mongodb.db_exists <name> <user> <password> <host> <port>
"""
dbs = db_list(user, password, host, port, authdb=authdb, ssl=ssl)
dbs = db_list(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if isinstance(dbs, str):
return False
@ -226,7 +253,14 @@ def db_exists(
def db_remove(
name, user=None, password=None, host=None, port=None, authdb=None, ssl=False
name,
user=None,
password=None,
host=None,
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Remove a MongoDB database.
@ -278,7 +312,9 @@ def db_remove(
salt '*' mongodb.db_remove <name> <user> <password> <host> <port>
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -304,6 +340,7 @@ def version(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Get MongoDB instance version.
@ -359,7 +396,9 @@ def version(
"""
# database is not passed into _connect here, which authdb typically falls
# back on. Probably not a bug but still confusing -W. Werner, 2022-02-10
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
err_msg = "Failed to connect to MongoDB database {}:{}".format(host, port)
log.error(err_msg)
@ -382,6 +421,7 @@ def user_find(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Get single user from MongoDB.
@ -418,7 +458,9 @@ def user_find(
salt '*' mongodb.user_find <name> <user> <password> <host> <port> <database> <authdb> <ssl>
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
err_msg = "Failed to connect to MongoDB database {}:{}".format(host, port)
log.error(err_msg)
@ -440,6 +482,7 @@ def user_list(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
List users of a MongoDB database.
@ -473,7 +516,9 @@ def user_list(
salt '*' mongodb.user_list <user> <password> <host> <port> <database> <authdb> <ssl>
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -508,6 +553,7 @@ def user_exists(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Checks if a user exists in MongoDB.
@ -541,7 +587,9 @@ def user_exists(
salt '*' mongodb.user_exists <name> <user> <password> <host> <port> <database> <authdb> <ssl>
"""
users = user_list(user, password, host, port, database, authdb, ssl=ssl)
users = user_list(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if isinstance(users, str):
return "Failed to connect to mongo database"
@ -564,6 +612,7 @@ def user_create(
authdb=None,
roles=None,
ssl=False,
verify_ssl=None,
):
"""
Create a MongoDB user.
@ -606,7 +655,9 @@ def user_create(
salt '*' mongodb.user_create <user_name> <user_password> <roles> <user> <password> <host> <port> <database> <authdb> <roles> <ssl>
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -634,6 +685,7 @@ def user_remove(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Remove a MongoDB user.
@ -667,7 +719,7 @@ def user_remove(
salt '*' mongodb.user_remove <name> <user> <password> <host> <port> <database> <authdb> <ssl>
"""
conn = _connect(user, password, host, port, ssl=ssl)
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl)
if not conn:
return "Failed to connect to mongo database"
@ -691,6 +743,7 @@ def user_roles_exists(
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Checks if a user of a MongoDB database has specified roles.
@ -768,7 +821,9 @@ def user_roles_exists(
# Here we pass in the database - does MongoDB return *all* of the roles
# across databases for a particular user?
users = user_list(user, password, host, port, database, authdb, ssl)
users = user_list(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if isinstance(users, str):
return "Failed to connect to mongo database"
@ -796,6 +851,7 @@ def user_grant_roles(
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Grant one or many roles to a MongoDB user.
@ -870,7 +926,9 @@ def user_grant_roles(
salt '*' mongodb.user_grant_roles janedoe '[{"role": "readWrite", "db": "dbname" }, {"role": "read", "db": "otherdb"}]' dbname admin adminpwd localhost 27017
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -902,6 +960,7 @@ def user_revoke_roles(
port=None,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Revoke one or many roles from a MongoDB user.
@ -973,7 +1032,9 @@ def user_revoke_roles(
salt '*' mongodb.user_revoke_roles janedoe '[{"role": "readWrite", "db": "dbname" }, {"role": "read", "db": "otherdb"}]' dbname admin adminpwd localhost 27017
"""
conn = _connect(user, password, host, port, authdb=authdb, ssl=ssl)
conn = _connect(
user, password, host, port, authdb=authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -1004,6 +1065,7 @@ def collection_create(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
.. versionadded:: 3006.0
@ -1038,7 +1100,7 @@ def collection_create(
salt '*' mongodb.collection_create mycollection <user> <password> <host> <port> <database>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl)
if not conn:
return "Failed to connect to mongo database"
@ -1063,6 +1125,7 @@ def collection_drop(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
.. versionadded:: 3006.0
@ -1094,7 +1157,7 @@ def collection_drop(
salt '*' mongodb.collection_drop mycollection <user> <password> <host> <port> <database>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl)
if not conn:
return "Failed to connect to mongo database"
@ -1118,6 +1181,7 @@ def collections_list(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
.. versionadded:: 3006.0
@ -1149,7 +1213,7 @@ def collections_list(
salt '*' mongodb.collections_list mycollection <user> <password> <host> <port> <database>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl)
if not conn:
return "Failed to connect to mongo database"
@ -1173,6 +1237,7 @@ def insert(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Insert an object or list of objects into a collection.
@ -1239,7 +1304,9 @@ def insert(
salt '*' mongodb.insert '[{"foo": "FOO", "bar": "BAR"}, {"foo": "BAZ", "bar": "BAM"}]' mycollection <user> <password> <host> <port> <database>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -1269,6 +1336,7 @@ def update_one(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Update a MongoDB document that matches the provided filter.
@ -1315,7 +1383,9 @@ def update_one(
salt '*' mongodb.update_one '{"_id": "my_minion"} {"bar": "BAR"}' mycollection <user> <password> <host> <port> <database> <ssl>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -1374,6 +1444,7 @@ def find(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Find an object or list of objects in a collection
@ -1414,7 +1485,9 @@ def find(
salt '*' mongodb.find mycollection '[{"foo": "FOO", "bar": "BAR"}]' <user> <password> <host> <port> <database> <authdb> <ssl>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"
@ -1453,6 +1526,7 @@ def remove(
w=1,
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Remove an object or list of objects from a collection
@ -1496,7 +1570,9 @@ def remove(
salt '*' mongodb.remove mycollection '[{"foo": "FOO", "bar": "BAR"}, {"foo": "BAZ", "bar": "BAM"}]' <user> <password> <host> <port> <database> <w> <authdb> <ssl>
"""
conn = _connect(user, password, host, port, database, authdb, ssl)
conn = _connect(
user, password, host, port, database, authdb, ssl=ssl, verify_ssl=verify_ssl
)
if not conn:
return "Failed to connect to mongo database"

View file

@ -18,7 +18,16 @@ def __virtual__():
return (False, "mongodb module could not be loaded")
def absent(name, user=None, password=None, host=None, port=None, authdb=None, ssl=None):
def absent(
name,
user=None,
password=None,
host=None,
port=None,
authdb=None,
ssl=None,
verify_ssl=None,
):
"""
Ensure that the named database is absent. Note that creation doesn't make
sense in MongoDB, since a database doesn't exist if it's empty.
@ -49,7 +58,14 @@ def absent(name, user=None, password=None, host=None, port=None, authdb=None, ss
ret = {"name": name, "changes": {}, "result": True, "comment": ""}
if __salt__["mongodb.db_exists"](
name, user, password, host, port, authdb=authdb, ssl=ssl
name,
user,
password,
host,
port,
authdb=authdb,
ssl=ssl,
verify_ssl=verify_ssl,
):
if __opts__["test"]:
ret["result"] = None
@ -58,7 +74,14 @@ def absent(name, user=None, password=None, host=None, port=None, authdb=None, ss
)
return ret
if __salt__["mongodb.db_remove"](
name, user, password, host, port, authdb=authdb, ssl=ssl
name,
user,
password,
host,
port,
authdb=authdb,
ssl=ssl,
verify_ssl=verify_ssl,
):
ret["comment"] = "Database {} has been removed".format(name)
ret["changes"][name] = "Absent"

View file

@ -26,6 +26,7 @@ def present(
authdb=None,
roles=None,
ssl=False,
verify_ssl=None,
):
"""
Ensure that the user is present with the specified properties
@ -110,6 +111,7 @@ def present(
database,
authdb,
ssl=ssl,
verify_ssl=verify_ssl,
)
if len(users) > 0:
# check for errors returned in users e.g.
@ -152,6 +154,7 @@ def present(
authdb=authdb,
roles=roles,
ssl=ssl,
verify_ssl=verify_ssl,
)
return ret
@ -178,6 +181,7 @@ def present(
authdb=authdb,
roles=roles,
ssl=ssl,
verify_ssl=verify_ssl,
):
ret["comment"] = "User {} has been created".format(name)
ret["changes"][name] = "Present"
@ -197,6 +201,7 @@ def absent(
database="admin",
authdb=None,
ssl=False,
verify_ssl=None,
):
"""
Ensure that the named user is absent
@ -230,7 +235,15 @@ def absent(
# check if user exists and remove it
user_exists = __salt__["mongodb.user_exists"](
name, user, password, host, port, database=database, authdb=authdb, ssl=ssl
name,
user,
password,
host,
port,
database=database,
authdb=authdb,
ssl=ssl,
verify_ssl=verify_ssl,
)
if user_exists is True:
if __opts__["test"]:
@ -246,6 +259,7 @@ def absent(
database=database,
authdb=authdb,
ssl=ssl,
verify_ssl=verify_ssl,
):
ret["comment"] = "User {} has been removed".format(name)
ret["changes"][name] = "Absent"

View file

@ -0,0 +1,160 @@
import logging
import time
import pytest
import salt.modules.mongodb as mongo_mod
from saltfactories.daemons.container import Container
from saltfactories.utils import random_string
from saltfactories.utils.ports import get_unused_localhost_port
docker = pytest.importorskip("docker")
log = logging.getLogger(__name__)
pytestmark = [
pytest.mark.skip_if_binaries_missing("dockerd"),
]
# TODO: Is there a better approach for waiting until the container is fully running? -W. Werner, 2021-07-27
class Timer:
def __init__(self, timeout=20):
self.start = time.time()
self.timeout = timeout
@property
def expired(self):
return time.time() - self.start > self.timeout
@pytest.fixture(scope="module", autouse="true")
def ensure_deps(states):
installation_result = states.pip.installed(
name="fnord",
pkgs=["pymongo"],
)
assert (
installation_result.result is True
), "unable to pip install requirements {}".format(installation_result.comment)
@pytest.fixture(scope="module")
def docker_client():
try:
client = docker.from_env()
except docker.errors.DockerException:
pytest.skip("Failed to get a connection to docker running on the system")
connectable = Container.client_connectable(client)
if connectable is not True: # pragma: nocover
pytest.skip(connectable)
return client
@pytest.fixture(scope="module")
def mongo_requiretls_container(salt_factories, docker_client, integration_files_dir):
mongo_port = get_unused_localhost_port()
container = salt_factories.get_container(
random_string("mongodb-server-"),
image_name="mongo",
docker_client=docker_client,
check_ports=[mongo_port],
container_run_kwargs={
"ports": {"27017/tcp": mongo_port},
"environment": {
"MONGO_INITDB_ROOT_USERNAME": "fnord",
"MONGO_INITDB_ROOT_PASSWORD": "fnord",
},
"volumes": {
str(integration_files_dir): {"bind": "/var/files", "mode": "z"},
},
},
)
with container.started(
"--tlsMode",
"requireTLS",
"--tlsCertificateKeyFile",
"/var/files/snakeoil.crtkey",
) as factory:
yield factory, mongo_port
@pytest.fixture(scope="module")
def mongo_no_requiretls_container(salt_factories, docker_client):
mongo_port = get_unused_localhost_port()
container = salt_factories.get_container(
random_string("mongodb-server-"),
image_name="mongo",
docker_client=docker_client,
check_ports=[mongo_port],
container_run_kwargs={
"ports": {"27017/tcp": mongo_port},
"environment": {
"MONGO_INITDB_ROOT_USERNAME": "fnord",
"MONGO_INITDB_ROOT_PASSWORD": "fnord",
},
},
)
with container.started() as factory:
yield factory, mongo_port
def test_when_mongo_requires_tls_and_module_ssl_is_False_connection_should_fail(
mongo_requiretls_container,
):
_, mongo_port = mongo_requiretls_container
result = mongo_mod.db_list(
user="fnord",
password="fnord",
host="127.0.0.1",
port=mongo_port,
ssl=False,
verify_ssl=False,
)
assert result == "Failed to connect to mongo database"
def test_when_mongo_requires_tls_and_module_ssl_is_True_connection_should_succeed(
mongo_requiretls_container,
):
_, mongo_port = mongo_requiretls_container
db_list = mongo_mod.db_list(
user="fnord",
password="fnord",
host="127.0.0.1",
port=mongo_port,
ssl=True,
verify_ssl=False,
)
assert "admin" in db_list
assert isinstance(db_list, list)
def test_when_mongo_not_requires_tls_and_module_ssl_is_False_connection_should_succeed(
mongo_no_requiretls_container,
):
_, mongo_port = mongo_no_requiretls_container
db_list = mongo_mod.db_list(
user="fnord",
password="fnord",
host="127.0.0.1",
port=mongo_port,
ssl=False,
verify_ssl=False,
)
assert "admin" in db_list
assert isinstance(db_list, list)
def test_when_mongo_not_requires_tls_and_module_ssl_is_True_connection_should_fail(
mongo_no_requiretls_container,
):
_, mongo_port = mongo_no_requiretls_container
result = mongo_mod.db_list(
user="fnord",
password="fnord",
host="127.0.0.1",
port=mongo_port,
ssl=True,
verify_ssl=False,
)
assert result == "Failed to connect to mongo database"

View file

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIUcCcgzyR0yKEuw4vz+GwZAm1FJEgwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDTALBgNVBAcMBExlaGkx
EjAQBgNVBAMMCWxvY2FsaG9zdDEQMA4GA1UECwwHdGVzdGluZzEfMB0GCSqGSIb3
DQEJARYQc2FsdEBleGFtcGxlLmNvbTAgFw0yMjAyMjIyMjEyMDNaGA8yMTIyMDEy
OTIyMTIwM1owcjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDTALBgNVBAcM
BExlaGkxEjAQBgNVBAMMCWxvY2FsaG9zdDEQMA4GA1UECwwHdGVzdGluZzEfMB0G
CSqGSIb3DQEJARYQc2FsdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMsOk6obfr1eHAHnI9u2Ba4abJSbNZw7nfE031ue7wrlmdez
aqhmAZuxZgefIDI3HtOVSJPjbqW0jqkPSg8tWCLLxFcOp773K92+g13jvpYAF01A
B4AoSdQtgsC4JAVKFrjKgm99IWOq0NKPYKYGOOJoacBkt6y2MS6dK4elcQSG9KZB
y7EnWAWs8TbJWzxsT/VDBNe+/eCcqCs6uvyT//0yxIHTdt/CLOzXC3eu6bRb0FE/
6pINLit3xZC0jTLDXKMC/8jtNTP345mp3QGQSJ98q5Q8cS3IwLmneh/Jf6NsV+Ao
YBq2wGBINImNSk8MTn2vlTS9cxkxDyQ/5nknbxECAwEAAaNTMFEwHQYDVR0OBBYE
FMUN2vcyIFiPmGvhdbE8GfA0nrF3MB8GA1UdIwQYMBaAFMUN2vcyIFiPmGvhdbE8
GfA0nrF3MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADEZHFa1
iExW1jFSDPK4F6hSEZgXuTHEHAmW2qwDr6FqKufhE1tOswyXTcuYDPHjlJWvDxAd
gjYm3EnNqNHchohNWMwJbw/I5oUO8rZtgmvZQPshKC2xvMgqsKULuNx+emT6hJGN
a5+rcwaSXJRRaT1gNr9DMFfE57s3HH8ggEiuaN2sherjCg9l5S0vYQi50TkRFu7m
rvfUZAO8quIbAGf9UW+5C4TecCcYhwR1Cj2WI2q1NgeNWzTR6M9Z4Olq5dnyttwS
7fJXCALvoaZxYZhzwSpz2a5BtrRXg1sCb3vWpmKisUmttwelrMZWPwDhw6Glm3qL
XlotRUDjwYYMP/o=
-----END CERTIFICATE-----

View file

@ -0,0 +1,51 @@
-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIUcCcgzyR0yKEuw4vz+GwZAm1FJEgwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDTALBgNVBAcMBExlaGkx
EjAQBgNVBAMMCWxvY2FsaG9zdDEQMA4GA1UECwwHdGVzdGluZzEfMB0GCSqGSIb3
DQEJARYQc2FsdEBleGFtcGxlLmNvbTAgFw0yMjAyMjIyMjEyMDNaGA8yMTIyMDEy
OTIyMTIwM1owcjELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxDTALBgNVBAcM
BExlaGkxEjAQBgNVBAMMCWxvY2FsaG9zdDEQMA4GA1UECwwHdGVzdGluZzEfMB0G
CSqGSIb3DQEJARYQc2FsdEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMsOk6obfr1eHAHnI9u2Ba4abJSbNZw7nfE031ue7wrlmdez
aqhmAZuxZgefIDI3HtOVSJPjbqW0jqkPSg8tWCLLxFcOp773K92+g13jvpYAF01A
B4AoSdQtgsC4JAVKFrjKgm99IWOq0NKPYKYGOOJoacBkt6y2MS6dK4elcQSG9KZB
y7EnWAWs8TbJWzxsT/VDBNe+/eCcqCs6uvyT//0yxIHTdt/CLOzXC3eu6bRb0FE/
6pINLit3xZC0jTLDXKMC/8jtNTP345mp3QGQSJ98q5Q8cS3IwLmneh/Jf6NsV+Ao
YBq2wGBINImNSk8MTn2vlTS9cxkxDyQ/5nknbxECAwEAAaNTMFEwHQYDVR0OBBYE
FMUN2vcyIFiPmGvhdbE8GfA0nrF3MB8GA1UdIwQYMBaAFMUN2vcyIFiPmGvhdbE8
GfA0nrF3MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADEZHFa1
iExW1jFSDPK4F6hSEZgXuTHEHAmW2qwDr6FqKufhE1tOswyXTcuYDPHjlJWvDxAd
gjYm3EnNqNHchohNWMwJbw/I5oUO8rZtgmvZQPshKC2xvMgqsKULuNx+emT6hJGN
a5+rcwaSXJRRaT1gNr9DMFfE57s3HH8ggEiuaN2sherjCg9l5S0vYQi50TkRFu7m
rvfUZAO8quIbAGf9UW+5C4TecCcYhwR1Cj2WI2q1NgeNWzTR6M9Z4Olq5dnyttwS
7fJXCALvoaZxYZhzwSpz2a5BtrRXg1sCb3vWpmKisUmttwelrMZWPwDhw6Glm3qL
XlotRUDjwYYMP/o=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLDpOqG369XhwB
5yPbtgWuGmyUmzWcO53xNN9bnu8K5ZnXs2qoZgGbsWYHnyAyNx7TlUiT426ltI6p
D0oPLVgiy8RXDqe+9yvdvoNd476WABdNQAeAKEnULYLAuCQFSha4yoJvfSFjqtDS
j2CmBjjiaGnAZLestjEunSuHpXEEhvSmQcuxJ1gFrPE2yVs8bE/1QwTXvv3gnKgr
Orr8k//9MsSB03bfwizs1wt3rum0W9BRP+qSDS4rd8WQtI0yw1yjAv/I7TUz9+OZ
qd0BkEiffKuUPHEtyMC5p3ofyX+jbFfgKGAatsBgSDSJjUpPDE59r5U0vXMZMQ8k
P+Z5J28RAgMBAAECggEAaWvq/DEELvqyHcbMFiC9eDOd1dVzEubczEMAB4hPYN/t
bFBo+n7jLNsANsrFo2x8o6rooGc+pedE/b7DW3fWP1J9YBlqu7mF270yZMd9xlDL
yD6K5l2EXxU1wiqYAOsDOvNgntNfR2iCvB7WNbwbQmilJs7jkVaR2DqfQ/B/6bHe
HTk4FAQGEUL3JgBdTl8uUstvpS87Kv6xH7VEFpXq3kdgAhTEjVKlBEeWzYgkISwK
W2rOj3AKGKjydGwlXTZgd7xzzt/m6AeYMYkLTPezjNXfFKptCtlMojaTQEIHQHaV
NaAJ2R6oAkdB6QwaM+wtgdS60YTToTY0dYq8kzJu1QKBgQDyGBESNS+Jr6suP51D
CLdvISi/6uMYqJHJBLKblNYwqnNqIvdHjPpV6s44/AHxKj20+mOlkorztRSb4i3S
WBZUYwJpT+lSbEjdVHSctc+hF+D+DZZemmOOo+84MoCQiTmdOejERc6w+9LcnXss
Ed7wYXUscEchjp4BWqLZN0g+YwKBgQDWuHrDyF1c2eSJJvuOQO4MBfcVkqIvQI+A
ccZt8MvgR9QYHKEK2rxTZpvvnVpceCY4mKII7PNHNc1S6tc40uXuIj721B3Sg48I
AePb63RUCmwx/MMlo6MEBv5zqyPvbBMCyWu1y55D06q1erNrsnbP/8k+xliHxeyN
iZOGkqXs+wKBgD5DMEjFgvdfRaA8Xh66ZCrhlVBegY968xuG6MSYr8mOXOaEHaK6
QDvOisEfFwTGP16HMw+HM9Nf0/APaId7fiqv2BPrqG85SDgcG22eWMrukD/mkLC9
9jLeOIz0eBo0IKwuE44/AdyEt4NjwSThZ7vc5LzMF48q1bo1bEJ/NEZPAoGATJ7D
3/0to6Z1MKPifB6bU1sFkoMisK3fBzySTETy23OGMZx1swPe0/v3hQenaPvO179P
gtPa8/w06nO2nSZUuicqRLXodmhPr9HM13srpZmahjPmBxZfY16Dig714ce0+Peb
IeIo9ZcggWXphHLIhuyFiYsJqFluUgtXw1utLeUCgYBNeIW3DchqnkpK4JnLYkDl
h3q5NGyRwLc02saYwZWCVUsjBSHSBG4SEBz9J0/ra+9Y/sIoCGPFGaf22ctqV1uw
HS3tVEZv36TAkf4CNHk5iQKgLwuBlcJJkKAZs3R1UopUnu6Yur4M/xLso1IH9eQw
r27CVW04xh5hqj+6tmupzg==
-----END PRIVATE KEY-----

View file

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLDpOqG369XhwB
5yPbtgWuGmyUmzWcO53xNN9bnu8K5ZnXs2qoZgGbsWYHnyAyNx7TlUiT426ltI6p
D0oPLVgiy8RXDqe+9yvdvoNd476WABdNQAeAKEnULYLAuCQFSha4yoJvfSFjqtDS
j2CmBjjiaGnAZLestjEunSuHpXEEhvSmQcuxJ1gFrPE2yVs8bE/1QwTXvv3gnKgr
Orr8k//9MsSB03bfwizs1wt3rum0W9BRP+qSDS4rd8WQtI0yw1yjAv/I7TUz9+OZ
qd0BkEiffKuUPHEtyMC5p3ofyX+jbFfgKGAatsBgSDSJjUpPDE59r5U0vXMZMQ8k
P+Z5J28RAgMBAAECggEAaWvq/DEELvqyHcbMFiC9eDOd1dVzEubczEMAB4hPYN/t
bFBo+n7jLNsANsrFo2x8o6rooGc+pedE/b7DW3fWP1J9YBlqu7mF270yZMd9xlDL
yD6K5l2EXxU1wiqYAOsDOvNgntNfR2iCvB7WNbwbQmilJs7jkVaR2DqfQ/B/6bHe
HTk4FAQGEUL3JgBdTl8uUstvpS87Kv6xH7VEFpXq3kdgAhTEjVKlBEeWzYgkISwK
W2rOj3AKGKjydGwlXTZgd7xzzt/m6AeYMYkLTPezjNXfFKptCtlMojaTQEIHQHaV
NaAJ2R6oAkdB6QwaM+wtgdS60YTToTY0dYq8kzJu1QKBgQDyGBESNS+Jr6suP51D
CLdvISi/6uMYqJHJBLKblNYwqnNqIvdHjPpV6s44/AHxKj20+mOlkorztRSb4i3S
WBZUYwJpT+lSbEjdVHSctc+hF+D+DZZemmOOo+84MoCQiTmdOejERc6w+9LcnXss
Ed7wYXUscEchjp4BWqLZN0g+YwKBgQDWuHrDyF1c2eSJJvuOQO4MBfcVkqIvQI+A
ccZt8MvgR9QYHKEK2rxTZpvvnVpceCY4mKII7PNHNc1S6tc40uXuIj721B3Sg48I
AePb63RUCmwx/MMlo6MEBv5zqyPvbBMCyWu1y55D06q1erNrsnbP/8k+xliHxeyN
iZOGkqXs+wKBgD5DMEjFgvdfRaA8Xh66ZCrhlVBegY968xuG6MSYr8mOXOaEHaK6
QDvOisEfFwTGP16HMw+HM9Nf0/APaId7fiqv2BPrqG85SDgcG22eWMrukD/mkLC9
9jLeOIz0eBo0IKwuE44/AdyEt4NjwSThZ7vc5LzMF48q1bo1bEJ/NEZPAoGATJ7D
3/0to6Z1MKPifB6bU1sFkoMisK3fBzySTETy23OGMZx1swPe0/v3hQenaPvO179P
gtPa8/w06nO2nSZUuicqRLXodmhPr9HM13srpZmahjPmBxZfY16Dig714ce0+Peb
IeIo9ZcggWXphHLIhuyFiYsJqFluUgtXw1utLeUCgYBNeIW3DchqnkpK4JnLYkDl
h3q5NGyRwLc02saYwZWCVUsjBSHSBG4SEBz9J0/ra+9Y/sIoCGPFGaf22ctqV1uw
HS3tVEZv36TAkf4CNHk5iQKgLwuBlcJJkKAZs3R1UopUnu6Yur4M/xLso1IH9eQw
r27CVW04xh5hqj+6tmupzg==
-----END PRIVATE KEY-----

View file

@ -741,10 +741,15 @@ def fake_pymongo():
@pytest.fixture(
params=[
(True, {"ssl": True}),
(False, {"ssl": False}),
(False, {"ssl": None}),
(False, {}),
(True, False, {"ssl": True}),
(True, False, {"ssl": True, "verify_ssl": None}),
(True, False, {"ssl": True, "verify_ssl": True}),
(True, True, {"ssl": True, "verify_ssl": False}),
(False, False, {"ssl": False, "verify_ssl": True}),
(False, True, {"ssl": False, "verify_ssl": False}),
(False, False, {"ssl": None, "verify_ssl": None}),
(False, True, {"ssl": None, "verify_ssl": False}),
(False, False, {}),
],
)
def ssl_kwargs(request):
@ -752,74 +757,98 @@ def ssl_kwargs(request):
def test_remove_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.remove(collection="whatever", **other_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_version_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.version(**other_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_user_roles_exists_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.user_roles_exists(
name="asdf", roles='["kaiser"]', database="bob", **other_kwargs
)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_user_grant_roles_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.user_grant_roles(
name="asdf", roles='["kaiser"]', database="bob", **other_kwargs
)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_user_revoke_roles_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.user_revoke_roles(
name="asdf", roles='["kaiser"]', database="bob", **other_kwargs
)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_insert_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.insert(
objects='["things"]', collection="fnord", **other_kwargs
)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_update_one_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.update_one(
objects='["things"]', collection="fnord", **other_kwargs
)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)
def test_find_should_pass_ssl_arg(ssl_kwargs):
expected_ssl, other_kwargs = ssl_kwargs
expected_ssl, expected_allow_invalid, other_kwargs = ssl_kwargs
salt.modules.mongodb.find(collection="fnord", **other_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_called_with(
host="mongodb-mod.example.com", port=44, ssl=expected_ssl
host="mongodb-mod.example.com",
port=44,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
)

View file

@ -60,16 +60,22 @@ def test_absent():
@pytest.mark.parametrize(
"expected_ssl, absent_kwargs",
"expected_ssl, expected_allow_invalid, absent_kwargs",
[
(True, {"name": "some_database", "ssl": True}),
(False, {"name": "some_database", "ssl": False}),
(False, {"name": "some_database", "ssl": None}),
(False, {"name": "some_database"}),
(True, False, {"name": "some_database", "ssl": True}),
(True, False, {"name": "some_database", "ssl": True, "verify_ssl": None}),
(True, False, {"name": "some_database", "ssl": True, "verify_ssl": True}),
(True, True, {"name": "some_database", "ssl": True, "verify_ssl": False}),
(False, False, {"name": "some_database", "ssl": False}),
(False, False, {"name": "some_database", "ssl": None}),
(False, False, {"name": "some_database"}),
(False, False, {"name": "some_database", "verify_ssl": None}),
(False, False, {"name": "some_database", "verify_ssl": True}),
(False, True, {"name": "some_database", "verify_ssl": False}),
],
)
def test_when_mongodb_database_remove_is_called_it_should_correctly_pass_ssl_argument(
expected_ssl, absent_kwargs
expected_ssl, expected_allow_invalid, absent_kwargs
):
# database from params needs to be in this return_value
salt.modules.mongodb.pymongo.MongoClient.return_value.database_names.return_value = [
@ -80,7 +86,12 @@ def test_when_mongodb_database_remove_is_called_it_should_correctly_pass_ssl_arg
mongodb_database.absent(**absent_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_has_calls(
[
call(host="mongodb.example.net", port=1982, ssl=expected_ssl),
call(
host="mongodb.example.net",
port=1982,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
# Not sure why database_names is in the call list given our
# return_value modifications above - it *should* have removed that
@ -88,7 +99,12 @@ def test_when_mongodb_database_remove_is_called_it_should_correctly_pass_ssl_arg
# other way to ensure that database_names/drop_database is out of
# the MongoClient mock call list, but it was taking too long.
call().database_names(),
call(host="mongodb.example.net", port=1982, ssl=expected_ssl),
call(
host="mongodb.example.net",
port=1982,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
call().drop_database("some_database"),
]

View file

@ -98,16 +98,21 @@ def test_absent():
@pytest.mark.parametrize(
"expected_ssl, absent_kwargs",
"expected_ssl, expected_allow_invalid, absent_kwargs",
[
(True, {"name": "mr_fnord", "ssl": True}),
(False, {"name": "mr_fnord", "ssl": False}),
(False, {"name": "mr_fnord", "ssl": None}),
(False, {"name": "mr_fnord"}),
(True, False, {"name": "mr_fnord", "ssl": True}),
(True, False, {"name": "mr_fnord", "ssl": True, "verify_ssl": None}),
(True, False, {"name": "mr_fnord", "ssl": True, "verify_ssl": True}),
(True, True, {"name": "mr_fnord", "ssl": True, "verify_ssl": False}),
(False, False, {"name": "mr_fnord", "ssl": False, "verify_ssl": True}),
(False, True, {"name": "mr_fnord", "ssl": None, "verify_ssl": False}),
(False, False, {"name": "mr_fnord"}),
(False, False, {"name": "mr_fnord", "verify_ssl": True}),
(False, True, {"name": "mr_fnord", "verify_ssl": False}),
],
)
def test_when_absent_is_called_it_should_pass_the_correct_ssl_argument_to_MongoClient(
expected_ssl, absent_kwargs
expected_ssl, expected_allow_invalid, absent_kwargs
):
with patch.dict(mongodb_user.__opts__, {"test": False}), patch(
"salt.modules.mongodb._LooseVersion", autospec=True, return_value=4
@ -123,21 +128,38 @@ def test_when_absent_is_called_it_should_pass_the_correct_ssl_argument_to_MongoC
mongodb_user.absent(**absent_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_has_calls(
[
call(host="example.com", port=42, ssl=expected_ssl),
call(
host="example.com",
port=42,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
call(host="example.com", port=42, ssl=expected_ssl),
call(
host="example.com",
port=42,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
]
)
# tlsAllowInvalidCertificates will be `not verify_ssl` - verify_ss is a much
# more common argument in Salt than tlsAllowInvalidCertificates.
@pytest.mark.parametrize(
"expected_ssl, present_kwargs",
"expected_ssl, expected_allow_invalid, present_kwargs",
[
(True, {"name": "mr_fnord", "ssl": True}),
(False, {"name": "mr_fnord", "ssl": False}),
(False, {"name": "mr_fnord", "ssl": None}),
(False, {"name": "mr_fnord"}),
(True, False, {"name": "mr_fnord", "ssl": True}),
(True, False, {"name": "mr_fnord", "ssl": True, "verify_ssl": None}),
(True, False, {"name": "mr_fnord", "ssl": True, "verify_ssl": True}),
(True, True, {"name": "mr_fnord", "ssl": True, "verify_ssl": False}),
(False, False, {"name": "mr_fnord", "ssl": False, "verify_ssl": True}),
(False, True, {"name": "mr_fnord", "ssl": None, "verify_ssl": False}),
(False, False, {"name": "mr_fnord"}),
(False, False, {"name": "mr_fnord", "verify_ssl": True}),
(False, True, {"name": "mr_fnord", "verify_ssl": False}),
],
)
@pytest.mark.parametrize(
@ -145,7 +167,7 @@ def test_when_absent_is_called_it_should_pass_the_correct_ssl_argument_to_MongoC
[[], [{"roles": [{"db": "kaiser"}, {"db": "fnord"}]}]],
)
def test_when_present_is_called_it_should_pass_the_correct_ssl_argument_to_MongoClient(
expected_ssl, present_kwargs, users
expected_ssl, expected_allow_invalid, present_kwargs, users
):
with patch.dict(mongodb_user.__opts__, {"test": False}):
salt.modules.mongodb.pymongo.database.Database.return_value.command.return_value = {
@ -154,9 +176,19 @@ def test_when_present_is_called_it_should_pass_the_correct_ssl_argument_to_Mongo
mongodb_user.present(passwd="fnord", **present_kwargs)
salt.modules.mongodb.pymongo.MongoClient.assert_has_calls(
[
call(host="example.com", port=42, ssl=expected_ssl),
call(
host="example.com",
port=42,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
call(host="example.com", port=42, ssl=expected_ssl),
call(
host="example.com",
port=42,
ssl=expected_ssl,
tlsAllowInvalidCertificates=expected_allow_invalid,
),
call().__bool__(),
]
)