sensu-plugins-mongodb-mrtrotl 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -0
  3. data/LICENSE +22 -0
  4. data/README.md +27 -0
  5. data/bin/check-mongodb-metric.rb +144 -0
  6. data/bin/check-mongodb-query-count.rb +267 -0
  7. data/bin/check-mongodb.py +1644 -0
  8. data/bin/check-mongodb.rb +5 -0
  9. data/bin/metrics-mongodb-replication.rb +254 -0
  10. data/bin/metrics-mongodb.rb +133 -0
  11. data/lib/bson/__init__.py +1347 -0
  12. data/lib/bson/__pycache__/__init__.cpython-310.pyc +0 -0
  13. data/lib/bson/__pycache__/_helpers.cpython-310.pyc +0 -0
  14. data/lib/bson/__pycache__/binary.cpython-310.pyc +0 -0
  15. data/lib/bson/__pycache__/code.cpython-310.pyc +0 -0
  16. data/lib/bson/__pycache__/codec_options.cpython-310.pyc +0 -0
  17. data/lib/bson/__pycache__/dbref.cpython-310.pyc +0 -0
  18. data/lib/bson/__pycache__/decimal128.cpython-310.pyc +0 -0
  19. data/lib/bson/__pycache__/errors.cpython-310.pyc +0 -0
  20. data/lib/bson/__pycache__/int64.cpython-310.pyc +0 -0
  21. data/lib/bson/__pycache__/json_util.cpython-310.pyc +0 -0
  22. data/lib/bson/__pycache__/max_key.cpython-310.pyc +0 -0
  23. data/lib/bson/__pycache__/min_key.cpython-310.pyc +0 -0
  24. data/lib/bson/__pycache__/objectid.cpython-310.pyc +0 -0
  25. data/lib/bson/__pycache__/raw_bson.cpython-310.pyc +0 -0
  26. data/lib/bson/__pycache__/regex.cpython-310.pyc +0 -0
  27. data/lib/bson/__pycache__/son.cpython-310.pyc +0 -0
  28. data/lib/bson/__pycache__/timestamp.cpython-310.pyc +0 -0
  29. data/lib/bson/__pycache__/tz_util.cpython-310.pyc +0 -0
  30. data/lib/bson/_cbson.cpython-310-x86_64-linux-gnu.so +0 -0
  31. data/lib/bson/_helpers.py +41 -0
  32. data/lib/bson/binary.py +364 -0
  33. data/lib/bson/code.py +101 -0
  34. data/lib/bson/codec_options.py +414 -0
  35. data/lib/bson/codec_options.pyi +100 -0
  36. data/lib/bson/dbref.py +133 -0
  37. data/lib/bson/decimal128.py +314 -0
  38. data/lib/bson/errors.py +35 -0
  39. data/lib/bson/int64.py +39 -0
  40. data/lib/bson/json_util.py +874 -0
  41. data/lib/bson/max_key.py +55 -0
  42. data/lib/bson/min_key.py +55 -0
  43. data/lib/bson/objectid.py +286 -0
  44. data/lib/bson/py.typed +2 -0
  45. data/lib/bson/raw_bson.py +175 -0
  46. data/lib/bson/regex.py +135 -0
  47. data/lib/bson/son.py +208 -0
  48. data/lib/bson/timestamp.py +124 -0
  49. data/lib/bson/tz_util.py +52 -0
  50. data/lib/gridfs/__init__.py +1015 -0
  51. data/lib/gridfs/__pycache__/__init__.cpython-310.pyc +0 -0
  52. data/lib/gridfs/__pycache__/errors.cpython-310.pyc +0 -0
  53. data/lib/gridfs/__pycache__/grid_file.cpython-310.pyc +0 -0
  54. data/lib/gridfs/errors.py +33 -0
  55. data/lib/gridfs/grid_file.py +907 -0
  56. data/lib/gridfs/py.typed +2 -0
  57. data/lib/pymongo/__init__.py +185 -0
  58. data/lib/pymongo/__pycache__/__init__.cpython-310.pyc +0 -0
  59. data/lib/pymongo/__pycache__/_csot.cpython-310.pyc +0 -0
  60. data/lib/pymongo/__pycache__/aggregation.cpython-310.pyc +0 -0
  61. data/lib/pymongo/__pycache__/auth.cpython-310.pyc +0 -0
  62. data/lib/pymongo/__pycache__/auth_aws.cpython-310.pyc +0 -0
  63. data/lib/pymongo/__pycache__/bulk.cpython-310.pyc +0 -0
  64. data/lib/pymongo/__pycache__/change_stream.cpython-310.pyc +0 -0
  65. data/lib/pymongo/__pycache__/client_options.cpython-310.pyc +0 -0
  66. data/lib/pymongo/__pycache__/client_session.cpython-310.pyc +0 -0
  67. data/lib/pymongo/__pycache__/collation.cpython-310.pyc +0 -0
  68. data/lib/pymongo/__pycache__/collection.cpython-310.pyc +0 -0
  69. data/lib/pymongo/__pycache__/command_cursor.cpython-310.pyc +0 -0
  70. data/lib/pymongo/__pycache__/common.cpython-310.pyc +0 -0
  71. data/lib/pymongo/__pycache__/compression_support.cpython-310.pyc +0 -0
  72. data/lib/pymongo/__pycache__/cursor.cpython-310.pyc +0 -0
  73. data/lib/pymongo/__pycache__/daemon.cpython-310.pyc +0 -0
  74. data/lib/pymongo/__pycache__/database.cpython-310.pyc +0 -0
  75. data/lib/pymongo/__pycache__/driver_info.cpython-310.pyc +0 -0
  76. data/lib/pymongo/__pycache__/encryption.cpython-310.pyc +0 -0
  77. data/lib/pymongo/__pycache__/encryption_options.cpython-310.pyc +0 -0
  78. data/lib/pymongo/__pycache__/errors.cpython-310.pyc +0 -0
  79. data/lib/pymongo/__pycache__/event_loggers.cpython-310.pyc +0 -0
  80. data/lib/pymongo/__pycache__/hello.cpython-310.pyc +0 -0
  81. data/lib/pymongo/__pycache__/helpers.cpython-310.pyc +0 -0
  82. data/lib/pymongo/__pycache__/max_staleness_selectors.cpython-310.pyc +0 -0
  83. data/lib/pymongo/__pycache__/message.cpython-310.pyc +0 -0
  84. data/lib/pymongo/__pycache__/mongo_client.cpython-310.pyc +0 -0
  85. data/lib/pymongo/__pycache__/monitor.cpython-310.pyc +0 -0
  86. data/lib/pymongo/__pycache__/monitoring.cpython-310.pyc +0 -0
  87. data/lib/pymongo/__pycache__/network.cpython-310.pyc +0 -0
  88. data/lib/pymongo/__pycache__/ocsp_cache.cpython-310.pyc +0 -0
  89. data/lib/pymongo/__pycache__/ocsp_support.cpython-310.pyc +0 -0
  90. data/lib/pymongo/__pycache__/operations.cpython-310.pyc +0 -0
  91. data/lib/pymongo/__pycache__/periodic_executor.cpython-310.pyc +0 -0
  92. data/lib/pymongo/__pycache__/pool.cpython-310.pyc +0 -0
  93. data/lib/pymongo/__pycache__/pyopenssl_context.cpython-310.pyc +0 -0
  94. data/lib/pymongo/__pycache__/read_concern.cpython-310.pyc +0 -0
  95. data/lib/pymongo/__pycache__/read_preferences.cpython-310.pyc +0 -0
  96. data/lib/pymongo/__pycache__/response.cpython-310.pyc +0 -0
  97. data/lib/pymongo/__pycache__/results.cpython-310.pyc +0 -0
  98. data/lib/pymongo/__pycache__/saslprep.cpython-310.pyc +0 -0
  99. data/lib/pymongo/__pycache__/server.cpython-310.pyc +0 -0
  100. data/lib/pymongo/__pycache__/server_api.cpython-310.pyc +0 -0
  101. data/lib/pymongo/__pycache__/server_description.cpython-310.pyc +0 -0
  102. data/lib/pymongo/__pycache__/server_selectors.cpython-310.pyc +0 -0
  103. data/lib/pymongo/__pycache__/server_type.cpython-310.pyc +0 -0
  104. data/lib/pymongo/__pycache__/settings.cpython-310.pyc +0 -0
  105. data/lib/pymongo/__pycache__/socket_checker.cpython-310.pyc +0 -0
  106. data/lib/pymongo/__pycache__/srv_resolver.cpython-310.pyc +0 -0
  107. data/lib/pymongo/__pycache__/ssl_context.cpython-310.pyc +0 -0
  108. data/lib/pymongo/__pycache__/ssl_support.cpython-310.pyc +0 -0
  109. data/lib/pymongo/__pycache__/topology.cpython-310.pyc +0 -0
  110. data/lib/pymongo/__pycache__/topology_description.cpython-310.pyc +0 -0
  111. data/lib/pymongo/__pycache__/typings.cpython-310.pyc +0 -0
  112. data/lib/pymongo/__pycache__/uri_parser.cpython-310.pyc +0 -0
  113. data/lib/pymongo/__pycache__/write_concern.cpython-310.pyc +0 -0
  114. data/lib/pymongo/_cmessage.cpython-310-x86_64-linux-gnu.so +0 -0
  115. data/lib/pymongo/_csot.py +118 -0
  116. data/lib/pymongo/aggregation.py +229 -0
  117. data/lib/pymongo/auth.py +549 -0
  118. data/lib/pymongo/auth_aws.py +94 -0
  119. data/lib/pymongo/bulk.py +513 -0
  120. data/lib/pymongo/change_stream.py +457 -0
  121. data/lib/pymongo/client_options.py +302 -0
  122. data/lib/pymongo/client_session.py +1112 -0
  123. data/lib/pymongo/collation.py +224 -0
  124. data/lib/pymongo/collection.py +3204 -0
  125. data/lib/pymongo/command_cursor.py +353 -0
  126. data/lib/pymongo/common.py +984 -0
  127. data/lib/pymongo/compression_support.py +149 -0
  128. data/lib/pymongo/cursor.py +1345 -0
  129. data/lib/pymongo/daemon.py +141 -0
  130. data/lib/pymongo/database.py +1202 -0
  131. data/lib/pymongo/driver_info.py +42 -0
  132. data/lib/pymongo/encryption.py +884 -0
  133. data/lib/pymongo/encryption_options.py +221 -0
  134. data/lib/pymongo/errors.py +365 -0
  135. data/lib/pymongo/event_loggers.py +221 -0
  136. data/lib/pymongo/hello.py +219 -0
  137. data/lib/pymongo/helpers.py +259 -0
  138. data/lib/pymongo/max_staleness_selectors.py +114 -0
  139. data/lib/pymongo/message.py +1440 -0
  140. data/lib/pymongo/mongo_client.py +2144 -0
  141. data/lib/pymongo/monitor.py +440 -0
  142. data/lib/pymongo/monitoring.py +1801 -0
  143. data/lib/pymongo/network.py +311 -0
  144. data/lib/pymongo/ocsp_cache.py +87 -0
  145. data/lib/pymongo/ocsp_support.py +372 -0
  146. data/lib/pymongo/operations.py +507 -0
  147. data/lib/pymongo/periodic_executor.py +183 -0
  148. data/lib/pymongo/pool.py +1660 -0
  149. data/lib/pymongo/py.typed +2 -0
  150. data/lib/pymongo/pyopenssl_context.py +383 -0
  151. data/lib/pymongo/read_concern.py +75 -0
  152. data/lib/pymongo/read_preferences.py +609 -0
  153. data/lib/pymongo/response.py +109 -0
  154. data/lib/pymongo/results.py +217 -0
  155. data/lib/pymongo/saslprep.py +113 -0
  156. data/lib/pymongo/server.py +247 -0
  157. data/lib/pymongo/server_api.py +170 -0
  158. data/lib/pymongo/server_description.py +285 -0
  159. data/lib/pymongo/server_selectors.py +153 -0
  160. data/lib/pymongo/server_type.py +32 -0
  161. data/lib/pymongo/settings.py +159 -0
  162. data/lib/pymongo/socket_checker.py +104 -0
  163. data/lib/pymongo/srv_resolver.py +126 -0
  164. data/lib/pymongo/ssl_context.py +39 -0
  165. data/lib/pymongo/ssl_support.py +99 -0
  166. data/lib/pymongo/topology.py +890 -0
  167. data/lib/pymongo/topology_description.py +639 -0
  168. data/lib/pymongo/typings.py +39 -0
  169. data/lib/pymongo/uri_parser.py +624 -0
  170. data/lib/pymongo/write_concern.py +129 -0
  171. data/lib/pymongo-4.2.0.dist-info/INSTALLER +1 -0
  172. data/lib/pymongo-4.2.0.dist-info/LICENSE +201 -0
  173. data/lib/pymongo-4.2.0.dist-info/METADATA +250 -0
  174. data/lib/pymongo-4.2.0.dist-info/RECORD +167 -0
  175. data/lib/pymongo-4.2.0.dist-info/REQUESTED +0 -0
  176. data/lib/pymongo-4.2.0.dist-info/WHEEL +6 -0
  177. data/lib/pymongo-4.2.0.dist-info/top_level.txt +3 -0
  178. data/lib/sensu-plugins-mongodb/metrics.rb +391 -0
  179. data/lib/sensu-plugins-mongodb/version.rb +9 -0
  180. data/lib/sensu-plugins-mongodb.rb +1 -0
  181. metadata +407 -0
@@ -0,0 +1,159 @@
1
+ # Copyright 2014-present MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
4
+ # may not use this file except in compliance with the License. You
5
+ # 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
12
+ # implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ """Represent MongoClient's configuration."""
16
+
17
+ import threading
18
+ import traceback
19
+
20
+ from bson.objectid import ObjectId
21
+ from pymongo import common, monitor, pool
22
+ from pymongo.common import LOCAL_THRESHOLD_MS, SERVER_SELECTION_TIMEOUT
23
+ from pymongo.errors import ConfigurationError
24
+ from pymongo.pool import PoolOptions
25
+ from pymongo.server_description import ServerDescription
26
+ from pymongo.topology_description import TOPOLOGY_TYPE
27
+
28
+
29
+ class TopologySettings(object):
30
+ def __init__(
31
+ self,
32
+ seeds=None,
33
+ replica_set_name=None,
34
+ pool_class=None,
35
+ pool_options=None,
36
+ monitor_class=None,
37
+ condition_class=None,
38
+ local_threshold_ms=LOCAL_THRESHOLD_MS,
39
+ server_selection_timeout=SERVER_SELECTION_TIMEOUT,
40
+ heartbeat_frequency=common.HEARTBEAT_FREQUENCY,
41
+ server_selector=None,
42
+ fqdn=None,
43
+ direct_connection=False,
44
+ load_balanced=None,
45
+ srv_service_name=common.SRV_SERVICE_NAME,
46
+ srv_max_hosts=0,
47
+ ):
48
+ """Represent MongoClient's configuration.
49
+
50
+ Take a list of (host, port) pairs and optional replica set name.
51
+ """
52
+ if heartbeat_frequency < common.MIN_HEARTBEAT_INTERVAL:
53
+ raise ConfigurationError(
54
+ "heartbeatFrequencyMS cannot be less than %d"
55
+ % (common.MIN_HEARTBEAT_INTERVAL * 1000,)
56
+ )
57
+
58
+ self._seeds = seeds or [("localhost", 27017)]
59
+ self._replica_set_name = replica_set_name
60
+ self._pool_class = pool_class or pool.Pool
61
+ self._pool_options = pool_options or PoolOptions()
62
+ self._monitor_class = monitor_class or monitor.Monitor
63
+ self._condition_class = condition_class or threading.Condition
64
+ self._local_threshold_ms = local_threshold_ms
65
+ self._server_selection_timeout = server_selection_timeout
66
+ self._server_selector = server_selector
67
+ self._fqdn = fqdn
68
+ self._heartbeat_frequency = heartbeat_frequency
69
+ self._direct = direct_connection
70
+ self._load_balanced = load_balanced
71
+ self._srv_service_name = srv_service_name
72
+ self._srv_max_hosts = srv_max_hosts or 0
73
+
74
+ self._topology_id = ObjectId()
75
+ # Store the allocation traceback to catch unclosed clients in the
76
+ # test suite.
77
+ self._stack = "".join(traceback.format_stack())
78
+
79
+ @property
80
+ def seeds(self):
81
+ """List of server addresses."""
82
+ return self._seeds
83
+
84
+ @property
85
+ def replica_set_name(self):
86
+ return self._replica_set_name
87
+
88
+ @property
89
+ def pool_class(self):
90
+ return self._pool_class
91
+
92
+ @property
93
+ def pool_options(self):
94
+ return self._pool_options
95
+
96
+ @property
97
+ def monitor_class(self):
98
+ return self._monitor_class
99
+
100
+ @property
101
+ def condition_class(self):
102
+ return self._condition_class
103
+
104
+ @property
105
+ def local_threshold_ms(self):
106
+ return self._local_threshold_ms
107
+
108
+ @property
109
+ def server_selection_timeout(self):
110
+ return self._server_selection_timeout
111
+
112
+ @property
113
+ def server_selector(self):
114
+ return self._server_selector
115
+
116
+ @property
117
+ def heartbeat_frequency(self):
118
+ return self._heartbeat_frequency
119
+
120
+ @property
121
+ def fqdn(self):
122
+ return self._fqdn
123
+
124
+ @property
125
+ def direct(self):
126
+ """Connect directly to a single server, or use a set of servers?
127
+
128
+ True if there is one seed and no replica_set_name.
129
+ """
130
+ return self._direct
131
+
132
+ @property
133
+ def load_balanced(self):
134
+ """True if the client was configured to connect to a load balancer."""
135
+ return self._load_balanced
136
+
137
+ @property
138
+ def srv_service_name(self):
139
+ """The srvServiceName."""
140
+ return self._srv_service_name
141
+
142
+ @property
143
+ def srv_max_hosts(self):
144
+ """The srvMaxHosts."""
145
+ return self._srv_max_hosts
146
+
147
+ def get_topology_type(self):
148
+ if self.load_balanced:
149
+ return TOPOLOGY_TYPE.LoadBalanced
150
+ elif self.direct:
151
+ return TOPOLOGY_TYPE.Single
152
+ elif self.replica_set_name is not None:
153
+ return TOPOLOGY_TYPE.ReplicaSetNoPrimary
154
+ else:
155
+ return TOPOLOGY_TYPE.Unknown
156
+
157
+ def get_server_descriptions(self):
158
+ """Initial dict of (address, ServerDescription) for all seeds."""
159
+ return dict([(address, ServerDescription(address)) for address in self.seeds])
@@ -0,0 +1,104 @@
1
+ # Copyright 2020-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
+ """Select / poll helper"""
16
+
17
+ import errno
18
+ import select
19
+ import sys
20
+ from typing import Any, Optional
21
+
22
+ # PYTHON-2320: Jython does not fully support poll on SSL sockets,
23
+ # https://bugs.jython.org/issue2900
24
+ _HAVE_POLL = hasattr(select, "poll") and not sys.platform.startswith("java")
25
+ _SelectError = getattr(select, "error", OSError)
26
+
27
+
28
+ def _errno_from_exception(exc):
29
+ if hasattr(exc, "errno"):
30
+ return exc.errno
31
+ if exc.args:
32
+ return exc.args[0]
33
+ return None
34
+
35
+
36
+ class SocketChecker(object):
37
+ def __init__(self) -> None:
38
+ self._poller: Optional[select.poll]
39
+ if _HAVE_POLL:
40
+ self._poller = select.poll()
41
+ else:
42
+ self._poller = None
43
+
44
+ def select(
45
+ self, sock: Any, read: bool = False, write: bool = False, timeout: Optional[float] = 0
46
+ ) -> bool:
47
+ """Select for reads or writes with a timeout in seconds (or None).
48
+
49
+ Returns True if the socket is readable/writable, False on timeout.
50
+ """
51
+ res: Any
52
+ while True:
53
+ try:
54
+ if self._poller:
55
+ mask = select.POLLERR | select.POLLHUP
56
+ if read:
57
+ mask = mask | select.POLLIN | select.POLLPRI
58
+ if write:
59
+ mask = mask | select.POLLOUT
60
+ self._poller.register(sock, mask)
61
+ try:
62
+ # poll() timeout is in milliseconds. select()
63
+ # timeout is in seconds.
64
+ timeout_ = None if timeout is None else timeout * 1000
65
+ res = self._poller.poll(timeout_)
66
+ # poll returns a possibly-empty list containing
67
+ # (fd, event) 2-tuples for the descriptors that have
68
+ # events or errors to report. Return True if the list
69
+ # is not empty.
70
+ return bool(res)
71
+ finally:
72
+ self._poller.unregister(sock)
73
+ else:
74
+ rlist = [sock] if read else []
75
+ wlist = [sock] if write else []
76
+ res = select.select(rlist, wlist, [sock], timeout)
77
+ # select returns a 3-tuple of lists of objects that are
78
+ # ready: subsets of the first three arguments. Return
79
+ # True if any of the lists are not empty.
80
+ return any(res)
81
+ except (_SelectError, IOError) as exc: # type: ignore
82
+ if _errno_from_exception(exc) in (errno.EINTR, errno.EAGAIN):
83
+ continue
84
+ raise
85
+
86
+ def socket_closed(self, sock: Any) -> bool:
87
+ """Return True if we know socket has been closed, False otherwise."""
88
+ try:
89
+ return self.select(sock, read=True)
90
+ except (RuntimeError, KeyError):
91
+ # RuntimeError is raised during a concurrent poll. KeyError
92
+ # is raised by unregister if the socket is not in the poller.
93
+ # These errors should not be possible since we protect the
94
+ # poller with a mutex.
95
+ raise
96
+ except ValueError:
97
+ # ValueError is raised by register/unregister/select if the
98
+ # socket file descriptor is negative or outside the range for
99
+ # select (> 1023).
100
+ return True
101
+ except Exception:
102
+ # Any other exceptions should be attributed to a closed
103
+ # or invalid socket.
104
+ return True
@@ -0,0 +1,126 @@
1
+ # Copyright 2019-present MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
4
+ # may not use this file except in compliance with the License. You
5
+ # 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
12
+ # implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ """Support for resolving hosts and options from mongodb+srv:// URIs."""
16
+
17
+ import ipaddress
18
+ import random
19
+
20
+ try:
21
+ from dns import resolver
22
+
23
+ _HAVE_DNSPYTHON = True
24
+ except ImportError:
25
+ _HAVE_DNSPYTHON = False
26
+
27
+ from pymongo.common import CONNECT_TIMEOUT
28
+ from pymongo.errors import ConfigurationError
29
+
30
+
31
+ # dnspython can return bytes or str from various parts
32
+ # of its API depending on version. We always want str.
33
+ def maybe_decode(text):
34
+ if isinstance(text, bytes):
35
+ return text.decode()
36
+ return text
37
+
38
+
39
+ # PYTHON-2667 Lazily call dns.resolver methods for compatibility with eventlet.
40
+ def _resolve(*args, **kwargs):
41
+ if hasattr(resolver, "resolve"):
42
+ # dnspython >= 2
43
+ return resolver.resolve(*args, **kwargs)
44
+ # dnspython 1.X
45
+ return resolver.query(*args, **kwargs)
46
+
47
+
48
+ _INVALID_HOST_MSG = (
49
+ "Invalid URI host: %s is not a valid hostname for 'mongodb+srv://'. "
50
+ "Did you mean to use 'mongodb://'?"
51
+ )
52
+
53
+
54
+ class _SrvResolver(object):
55
+ def __init__(self, fqdn, connect_timeout, srv_service_name, srv_max_hosts=0):
56
+ self.__fqdn = fqdn
57
+ self.__srv = srv_service_name
58
+ self.__connect_timeout = connect_timeout or CONNECT_TIMEOUT
59
+ self.__srv_max_hosts = srv_max_hosts or 0
60
+ # Validate the fully qualified domain name.
61
+ try:
62
+ ipaddress.ip_address(fqdn)
63
+ raise ConfigurationError(_INVALID_HOST_MSG % ("an IP address",))
64
+ except ValueError:
65
+ pass
66
+
67
+ try:
68
+ self.__plist = self.__fqdn.split(".")[1:]
69
+ except Exception:
70
+ raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,))
71
+ self.__slen = len(self.__plist)
72
+ if self.__slen < 2:
73
+ raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,))
74
+
75
+ def get_options(self):
76
+ try:
77
+ results = _resolve(self.__fqdn, "TXT", lifetime=self.__connect_timeout)
78
+ except (resolver.NoAnswer, resolver.NXDOMAIN):
79
+ # No TXT records
80
+ return None
81
+ except Exception as exc:
82
+ raise ConfigurationError(str(exc))
83
+ if len(results) > 1:
84
+ raise ConfigurationError("Only one TXT record is supported")
85
+ return (b"&".join([b"".join(res.strings) for res in results])).decode("utf-8")
86
+
87
+ def _resolve_uri(self, encapsulate_errors):
88
+ try:
89
+ results = _resolve(
90
+ "_" + self.__srv + "._tcp." + self.__fqdn, "SRV", lifetime=self.__connect_timeout
91
+ )
92
+ except Exception as exc:
93
+ if not encapsulate_errors:
94
+ # Raise the original error.
95
+ raise
96
+ # Else, raise all errors as ConfigurationError.
97
+ raise ConfigurationError(str(exc))
98
+ return results
99
+
100
+ def _get_srv_response_and_hosts(self, encapsulate_errors):
101
+ results = self._resolve_uri(encapsulate_errors)
102
+
103
+ # Construct address tuples
104
+ nodes = [
105
+ (maybe_decode(res.target.to_text(omit_final_dot=True)), res.port) for res in results
106
+ ]
107
+
108
+ # Validate hosts
109
+ for node in nodes:
110
+ try:
111
+ nlist = node[0].split(".")[1:][-self.__slen :]
112
+ except Exception:
113
+ raise ConfigurationError("Invalid SRV host: %s" % (node[0],))
114
+ if self.__plist != nlist:
115
+ raise ConfigurationError("Invalid SRV host: %s" % (node[0],))
116
+ if self.__srv_max_hosts:
117
+ nodes = random.sample(nodes, min(self.__srv_max_hosts, len(nodes)))
118
+ return results, nodes
119
+
120
+ def get_hosts(self):
121
+ _, nodes = self._get_srv_response_and_hosts(True)
122
+ return nodes
123
+
124
+ def get_hosts_and_min_ttl(self):
125
+ results, nodes = self._get_srv_response_and_hosts(False)
126
+ return nodes, results.rrset.ttl
@@ -0,0 +1,39 @@
1
+ # Copyright 2014-present MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
4
+ # may not use this file except in compliance with the License. You
5
+ # 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
12
+ # implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ """A fake SSLContext implementation."""
16
+
17
+ import ssl as _ssl
18
+
19
+ # PROTOCOL_TLS_CLIENT is Python 3.6+
20
+ PROTOCOL_SSLv23 = getattr(_ssl, "PROTOCOL_TLS_CLIENT", _ssl.PROTOCOL_SSLv23)
21
+ OP_NO_SSLv2 = getattr(_ssl, "OP_NO_SSLv2", 0)
22
+ OP_NO_SSLv3 = getattr(_ssl, "OP_NO_SSLv3", 0)
23
+ OP_NO_COMPRESSION = getattr(_ssl, "OP_NO_COMPRESSION", 0)
24
+ # Python 3.7+, OpenSSL 1.1.0h+
25
+ OP_NO_RENEGOTIATION = getattr(_ssl, "OP_NO_RENEGOTIATION", 0)
26
+
27
+ HAS_SNI = getattr(_ssl, "HAS_SNI", False)
28
+ IS_PYOPENSSL = False
29
+
30
+ # Errors raised by SSL sockets when in non-blocking mode.
31
+ BLOCKING_IO_ERRORS = (_ssl.SSLWantReadError, _ssl.SSLWantWriteError)
32
+
33
+ # Base Exception class
34
+ SSLError = _ssl.SSLError
35
+
36
+ from ssl import SSLContext # noqa: F401,E402
37
+
38
+ if hasattr(_ssl, "VERIFY_CRL_CHECK_LEAF"):
39
+ from ssl import VERIFY_CRL_CHECK_LEAF # noqa: F401
@@ -0,0 +1,99 @@
1
+ # Copyright 2014-present MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
4
+ # may not use this file except in compliance with the License. You
5
+ # 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
12
+ # implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+
15
+ """Support for SSL in PyMongo."""
16
+
17
+ from pymongo.errors import ConfigurationError
18
+
19
+ HAVE_SSL = True
20
+
21
+ try:
22
+ import pymongo.pyopenssl_context as _ssl
23
+ except ImportError:
24
+ try:
25
+ import pymongo.ssl_context as _ssl # type: ignore[no-redef]
26
+ except ImportError:
27
+ HAVE_SSL = False
28
+
29
+
30
+ if HAVE_SSL:
31
+ # Note: The validate* functions below deal with users passing
32
+ # CPython ssl module constants to configure certificate verification
33
+ # at a high level. This is legacy behavior, but requires us to
34
+ # import the ssl module even if we're only using it for this purpose.
35
+ import ssl as _stdlibssl # noqa
36
+ from ssl import CERT_NONE, CERT_REQUIRED
37
+
38
+ HAS_SNI = _ssl.HAS_SNI
39
+ IPADDR_SAFE = True
40
+ SSLError = _ssl.SSLError
41
+ BLOCKING_IO_ERRORS = _ssl.BLOCKING_IO_ERRORS
42
+
43
+ def get_ssl_context(
44
+ certfile,
45
+ passphrase,
46
+ ca_certs,
47
+ crlfile,
48
+ allow_invalid_certificates,
49
+ allow_invalid_hostnames,
50
+ disable_ocsp_endpoint_check,
51
+ ):
52
+ """Create and return an SSLContext object."""
53
+ verify_mode = CERT_NONE if allow_invalid_certificates else CERT_REQUIRED
54
+ ctx = _ssl.SSLContext(_ssl.PROTOCOL_SSLv23)
55
+ if verify_mode != CERT_NONE:
56
+ ctx.check_hostname = not allow_invalid_hostnames
57
+ else:
58
+ ctx.check_hostname = False
59
+ if hasattr(ctx, "check_ocsp_endpoint"):
60
+ ctx.check_ocsp_endpoint = not disable_ocsp_endpoint_check
61
+ if hasattr(ctx, "options"):
62
+ # Explicitly disable SSLv2, SSLv3 and TLS compression. Note that
63
+ # up to date versions of MongoDB 2.4 and above already disable
64
+ # SSLv2 and SSLv3, python disables SSLv2 by default in >= 2.7.7
65
+ # and >= 3.3.4 and SSLv3 in >= 3.4.3.
66
+ ctx.options |= _ssl.OP_NO_SSLv2
67
+ ctx.options |= _ssl.OP_NO_SSLv3
68
+ ctx.options |= _ssl.OP_NO_COMPRESSION
69
+ ctx.options |= _ssl.OP_NO_RENEGOTIATION
70
+ if certfile is not None:
71
+ try:
72
+ ctx.load_cert_chain(certfile, None, passphrase)
73
+ except _ssl.SSLError as exc:
74
+ raise ConfigurationError("Private key doesn't match certificate: %s" % (exc,))
75
+ if crlfile is not None:
76
+ if _ssl.IS_PYOPENSSL:
77
+ raise ConfigurationError("tlsCRLFile cannot be used with PyOpenSSL")
78
+ # Match the server's behavior.
79
+ setattr(ctx, "verify_flags", getattr(_ssl, "VERIFY_CRL_CHECK_LEAF", 0)) # noqa
80
+ ctx.load_verify_locations(crlfile)
81
+ if ca_certs is not None:
82
+ ctx.load_verify_locations(ca_certs)
83
+ elif verify_mode != CERT_NONE:
84
+ ctx.load_default_certs()
85
+ ctx.verify_mode = verify_mode
86
+ return ctx
87
+
88
+ else:
89
+
90
+ class SSLError(Exception): # type: ignore
91
+ pass
92
+
93
+ HAS_SNI = False
94
+ IPADDR_SAFE = False
95
+ BLOCKING_IO_ERRORS = () # type: ignore
96
+
97
+ def get_ssl_context(*dummy): # type: ignore
98
+ """No ssl module, raise ConfigurationError."""
99
+ raise ConfigurationError("The ssl module is not available.")