123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- # Copyright (c) "Neo4j"
- # Neo4j Sweden AB [https://neo4j.com]
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # https://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from __future__ import annotations
- import typing as t
- from .._async_compat.concurrency import AsyncLock
- from .._conf import (
- _trust_to_trusted_certificates,
- Config,
- DeprecatedAlternative,
- TrustAll,
- TrustCustomCAs,
- TrustSystemCAs,
- )
- if t.TYPE_CHECKING:
- import ssl
- from .._auth_management import ClientCertificate
- class AsyncPoolConfig(Config):
- """Connection pool configuration."""
- #: Max Connection Lifetime
- max_connection_lifetime = 3600 # seconds
- # The maximum duration the driver will keep a connection for before being
- # removed from the pool.
- #: Timeout after which idle connections will be checked for liveness
- #: before returned from the pool.
- liveness_check_timeout = None
- #: Max Connection Pool Size
- max_connection_pool_size = 100
- # The maximum total number of connections allowed, per host
- # (i.e. cluster nodes), to be managed by the connection pool.
- #: Connection Timeout
- connection_timeout = 30.0 # seconds
- # The maximum amount of time to wait for a TCP connection to be
- # established.
- #: Trust
- trust = DeprecatedAlternative(
- "trusted_certificates", _trust_to_trusted_certificates
- )
- # Specify how to determine the authenticity of encryption certificates
- # provided by the Neo4j instance on connection.
- #: Custom Resolver
- resolver = None
- # Custom resolver function, returning list of resolved addresses.
- #: Encrypted
- encrypted = False
- # Specify whether to use an encrypted connection between the driver and
- # server.
- #: SSL Certificates to Trust
- trusted_certificates = TrustSystemCAs()
- # Specify how to determine the authenticity of encryption certificates
- # provided by the Neo4j instance on connection.
- # * `neo4j.TrustSystemCAs()`: Use system trust store. (default)
- # * `neo4j.TrustAll()`: Trust any certificate.
- # * `neo4j.TrustCustomCAs("<path>", ...)`:
- # Trust the specified certificate(s).
- #: Certificate to use for mTLS as 2nd authentication factor.
- client_certificate = None
- #: Custom SSL context to use for wrapping sockets
- ssl_context = None
- # Use any custom SSL context to wrap sockets.
- # Overwrites `trusted_certificates` and `encrypted`.
- # The use of this option is strongly discouraged.
- #: User Agent (Python Driver Specific)
- user_agent = None
- # Specify the client agent name.
- #: Socket Keep Alive (Python and .NET Driver Specific)
- keep_alive = True
- # Specify whether TCP keep-alive should be enabled.
- #: Authentication provider
- auth = None
- #: Lowest notification severity for the server to return
- notifications_min_severity = None
- #: List of notification classifications/categories for the server to ignore
- notifications_disabled_classifications = None
- #: Opt-Out of telemetry collection
- telemetry_disabled = False
- _ssl_context_cache: ssl.SSLContext | None
- _ssl_context_cache_lock: AsyncLock
- def __init__(self, *args, **kwargs) -> None:
- super().__init__(*args, **kwargs)
- self._ssl_context_cache = None
- self._ssl_context_cache_lock = AsyncLock()
- async def get_ssl_context(self) -> ssl.SSLContext | None:
- if self.ssl_context is not None:
- return self.ssl_context
- if not self.encrypted:
- return None
- client_cert: ClientCertificate | None = None
- # try to serve the cached ssl context
- async with self._ssl_context_cache_lock:
- if self._ssl_context_cache is not None:
- if self.client_certificate is None:
- return self._ssl_context_cache
- client_cert = await self.client_certificate.get_certificate()
- if client_cert is None:
- return self._ssl_context_cache
- elif self.client_certificate is not None:
- client_cert = await self.client_certificate.get_certificate()
- import ssl
- # SSL stands for Secure Sockets Layer and was originally created by
- # Netscape.
- # SSLv2 and SSLv3 are the 2 versions of this protocol (SSLv1 was
- # never publicly released).
- # After SSLv3, SSL was renamed to TLS.
- # TLS stands for Transport Layer Security and started with TLSv1.0
- # which is an upgraded version of SSLv3.
- # SSLv2 - (Disabled)
- # SSLv3 - (Disabled)
- # TLS 1.0 - Released in 1999, published as RFC 2246. (Disabled)
- # TLS 1.1 - Released in 2006, published as RFC 4346. (Disabled)
- # TLS 1.2 - Released in 2008, published as RFC 5246.
- # https://docs.python.org/3.7/library/ssl.html#ssl.PROTOCOL_TLS_CLIENT
- ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
- # For recommended security options see
- # https://docs.python.org/3.10/library/ssl.html#protocol-versions
- ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
- if isinstance(self.trusted_certificates, TrustAll):
- # trust any certificate
- ssl_context.check_hostname = False
- # https://docs.python.org/3.7/library/ssl.html#ssl.CERT_NONE
- ssl_context.verify_mode = ssl.CERT_NONE
- elif isinstance(self.trusted_certificates, TrustCustomCAs):
- # trust the specified certificate(s)
- ssl_context.check_hostname = True
- ssl_context.verify_mode = ssl.CERT_REQUIRED
- for cert in self.trusted_certificates.certs:
- ssl_context.load_verify_locations(cert)
- else:
- # default
- # trust system CA certificates
- ssl_context.check_hostname = True
- ssl_context.verify_mode = ssl.CERT_REQUIRED
- # Must be load_default_certs, not set_default_verify_paths to
- # work on Windows with system CAs.
- ssl_context.load_default_certs()
- if client_cert is not None:
- ssl_context.load_cert_chain(
- client_cert.certfile,
- keyfile=client_cert.keyfile,
- password=client_cert.password,
- )
- self._ssl_context_cache = ssl_context
- return ssl_context
|