Skip to content

Commit 9124492

Browse files
absurdfarcedkropachev
authored andcommitted
PYTHON-1356 Create session-specific protocol handlers to contain session-specific CLE policies (datastax#1165)
1 parent a1c6bf7 commit 9124492

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

cassandra/cluster.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,12 +2668,6 @@ def __init__(self, cluster, hosts, keyspace=None):
26682668

26692669
self.encoder = Encoder()
26702670

2671-
if self.cluster.column_encryption_policy is not None:
2672-
try:
2673-
self.client_protocol_handler.column_encryption_policy = self.cluster.column_encryption_policy
2674-
except AttributeError:
2675-
log.info("Unable to set column encryption policy for session")
2676-
26772671
# create connection pools in parallel
26782672
self._initial_connect_futures = set()
26792673
for host in hosts:
@@ -2694,6 +2688,15 @@ def __init__(self, cluster, hosts, keyspace=None):
26942688
self.session_id = uuid.uuid4()
26952689
self._graph_paging_available = self._check_graph_paging_available()
26962690

2691+
if self.cluster.column_encryption_policy is not None:
2692+
try:
2693+
self.client_protocol_handler = type(
2694+
str(self.session_id) + "-ProtocolHandler",
2695+
(ProtocolHandler,),
2696+
{"column_encryption_policy": self.cluster.column_encryption_policy})
2697+
except AttributeError:
2698+
log.info("Unable to set column encryption policy for session")
2699+
26972700
if self.cluster.monitor_reporting_enabled:
26982701
cc_host = self.cluster.get_control_connection_host()
26992702
valid_insights_version = (cc_host and version_supports_insights(cc_host.dse_version))

tests/integration/standard/column_encryption/test_policies.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ def test_end_to_end_simple(self):
9595
self.assertEquals(expected, encrypted)
9696
self.assertEquals(expected, unencrypted)
9797

98-
def test_end_to_end_different_cle_contexts(self):
98+
def test_end_to_end_different_cle_contexts_different_ivs(self):
99+
"""
100+
Test to validate PYTHON-1350. We should be able to decode the data from two different contexts (with two different IVs)
101+
since the IV used to decrypt the data is actually now stored with the data.
102+
"""
99103

100104
expected = 2
101105

@@ -133,3 +137,34 @@ def test_end_to_end_different_cle_contexts(self):
133137
(encrypted,unencrypted) = session2.execute("select encrypted, unencrypted from foo.bar where unencrypted = %s allow filtering", (expected,)).one()
134138
self.assertEquals(expected, encrypted)
135139
self.assertEquals(expected, unencrypted)
140+
141+
def test_end_to_end_different_cle_contexts_different_policies(self):
142+
"""
143+
Test to validate PYTHON-1356. Class variables used to pass CLE policy down to protocol handler shouldn't persist.
144+
"""
145+
146+
expected = 3
147+
148+
key = os.urandom(AES256_KEY_SIZE_BYTES)
149+
(col_desc, cl_policy) = self._create_policy(key)
150+
cluster = TestCluster(column_encryption_policy=cl_policy)
151+
session = cluster.connect()
152+
self._recreate_keyspace(session)
153+
154+
# Use encode_and_encrypt helper function to populate date
155+
session.execute("insert into foo.bar (encrypted, unencrypted) values (%s,%s)",(cl_policy.encode_and_encrypt(col_desc, expected), expected))
156+
157+
# We now open a new session _without_ the CLE policy specified. We should _not_ be able to read decrypted bits from this session.
158+
cluster2 = TestCluster()
159+
session2 = cluster2.connect()
160+
161+
# A straight select from the database will now return the decrypted bits. We select both encrypted and unencrypted
162+
# values here to confirm that we don't interfere with regular processing of unencrypted vals.
163+
(encrypted,unencrypted) = session2.execute("select encrypted, unencrypted from foo.bar where unencrypted = %s allow filtering", (expected,)).one()
164+
self.assertEquals(cl_policy.encode_and_encrypt(col_desc, expected), encrypted)
165+
self.assertEquals(expected, unencrypted)
166+
167+
# Confirm the same behaviour from a subsequent prepared statement as well
168+
prepared = session2.prepare("select encrypted, unencrypted from foo.bar where unencrypted = ? allow filtering")
169+
(encrypted,unencrypted) = session2.execute(prepared, [expected]).one()
170+
self.assertEquals(cl_policy.encode_and_encrypt(col_desc, expected), encrypted)

0 commit comments

Comments
 (0)