@@ -51,6 +51,117 @@ To enable SSL with version 3.17.0 and higher, set :attr:`.Cluster.ssl_context` t
5151``ssl.SSLContext `` instance. The legacy :attr: `.Cluster.ssl_options ` argument remains
5252in the API only to raise an error with migration guidance when it is used.
5353
54+ .. _ssl-options-migration :
55+
56+ Migrating from ``ssl_options ``
57+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58+
59+ Replace the legacy options dictionary with a context configured through the
60+ standard-library ``ssl `` API. For example, replace:
61+
62+ .. code-block :: python
63+
64+ import ssl
65+ from cassandra.cluster import Cluster
66+
67+ cluster = Cluster(
68+ [' node.example.com' ],
69+ ssl_options = {
70+ ' ca_certs' : ' /path/to/rootca.pem' ,
71+ ' cert_reqs' : ssl.CERT_REQUIRED ,
72+ ' check_hostname' : True ,
73+ },
74+ )
75+
76+ with:
77+
78+ .. code-block :: python
79+
80+ context = ssl.create_default_context(cafile = ' /path/to/rootca.pem' )
81+ context.check_hostname = True
82+
83+ cluster = Cluster(
84+ [' node.example.com' ],
85+ ssl_context = context,
86+ )
87+
88+ Use the following mappings for other legacy options:
89+
90+ .. list-table :: ``ssl_options`` migration reference
91+ :header-rows: 1
92+ :widths: 22 38 40
93+
94+ * - Legacy option
95+ - Standard-library context
96+ - Twisted/Eventlet pyOpenSSL context
97+ * - ``ca_certs ``
98+ - ``context.load_verify_locations(path) ``
99+ - ``context.load_verify_locations(path) ``
100+ * - ``certfile `` and ``keyfile ``
101+ - ``context.load_cert_chain(certfile, keyfile, password) ``
102+ - ``context.use_certificate_file(certfile) `` and
103+ ``context.use_privatekey_file(keyfile) ``
104+ * - ``cert_reqs ``
105+ - ``context.verify_mode ``
106+ - ``context.set_verify(mode, callback) ``
107+ * - ``check_hostname ``
108+ - ``context.check_hostname ``
109+ - There is no direct context attribute. Configure hostname verification
110+ in a vetted pyOpenSSL verification layer, or migrate to a
111+ standard-library-backed reactor when hostname verification is required.
112+ * - ``ciphers ``
113+ - ``context.set_ciphers(value) ``
114+ - ``context.set_cipher_list(value.encode('ascii')) ``
115+ * - ``ssl_version ``
116+ - Start with ``ssl.PROTOCOL_TLS_CLIENT `` and configure
117+ ``minimum_version `` and ``maximum_version `` when pinning is required.
118+ - Start with ``SSL.TLS_CLIENT_METHOD `` and configure protocol bounds on
119+ the context when pinning is required.
120+ * - ``server_hostname ``
121+ - The driver derives this from the endpoint. Use
122+ :class: `~cassandra.connection.SniEndPoint ` when explicit SNI routing is
123+ required.
124+ - The driver derives this from the endpoint. Use
125+ :class: `~cassandra.connection.SniEndPoint ` when explicit SNI routing is
126+ required.
127+ * - ``server_side ``, ``do_handshake_on_connect ``, and
128+ ``suppress_ragged_eofs ``
129+ - No migration. The driver owns client-side socket creation and TLS
130+ handshakes; these low-level overrides are no longer configurable.
131+ - No migration. The driver owns client-side socket creation and TLS
132+ handshakes; these low-level overrides are no longer configurable.
133+
134+ An empty ``ssl_options={} `` previously left the intended verification policy
135+ ambiguous. Replace it with an explicit context. For an insecure development
136+ connection with no certificate verification:
137+
138+ .. code-block :: python
139+
140+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT )
141+ context.check_hostname = False
142+ context.verify_mode = ssl.CERT_NONE
143+ cluster = Cluster([' 127.0.0.1' ], ssl_context = context)
144+
145+ Do not use this configuration in production. Prefer
146+ ``ssl.create_default_context() `` with a trusted CA and hostname verification.
147+
148+ For mutual TLS, load the client certificate and private key on the context:
149+
150+ .. code-block :: python
151+
152+ context = ssl.create_default_context(cafile = ' /path/to/rootca.pem' )
153+ context.load_cert_chain(
154+ certfile = ' /path/to/client.crt' ,
155+ keyfile = ' /path/to/client.key' ,
156+ password = ' optional-key-password' ,
157+ )
158+ cluster = Cluster([' node.example.com' ], ssl_context = context)
159+
160+ Twisted and Eventlet require an ``OpenSSL.SSL.Context `` instead of a standard
161+ ``ssl.SSLContext ``. See `SSL with Twisted or Eventlet `_ below for a complete
162+ example. Cloud secure-connect bundles require no migration; the driver creates
163+ their TLS context internally.
164+
54165If you create your SSLContext using `ssl.create_default_context <https://docs.python.org/3/library/ssl.html#ssl.create_default_context >`_,
55166be aware that SSLContext.check_hostname is set to True by default, so hostname validation is done
56167by Python rather than the driver. The driver uses the endpoint address as the TLS server name.
0 commit comments