Support ZMQ Curve for transport encryption#1515
Conversation
| self.log.warning( | ||
| "Kernel is running over TCP without encryption." | ||
| " All communication (including code and outputs) is sent in plain text" | ||
| " and is susceptible to eavesdropping." | ||
| " Use IPC transport or set IPKernelApp.enable_curve=True to enable" | ||
| " CurveZMQ encryption." | ||
| ) |
There was a problem hiding this comment.
nbclient downstream tests are failing due to addition of this warning, see:
E AssertionError: assert '[IPKernelApp] WARNING | Kernel is running over TCP without encryption. All communication (including code and outputs) is sent in plain text and is susceptible to eavesdropping. Use IPC transport or set IPKernelApp.enable_curve=True to enable CurveZMQ encryption.\n[IPKernelApp] WARNING | Kernel is running over TCP without encryption. All communication (including code and outputs) is sent in plain text and is susceptible to eavesdropping. Use IPC transport or set IPKernelApp.enable_curve=True to enable CurveZMQ encryption.' == ''
I believe we should keep it and update nbclient tests, any objections?
There was a problem hiding this comment.
yeah, nbclient tests shouldn't fail if warnings are logged from another package, that's a problem in the test suite
| ).tag(config=True) | ||
|
|
||
| enable_curve = Bool( | ||
| bool(int(os.environ.get("JUPYTER_ENABLE_CURVE", "0"))), |
There was a problem hiding this comment.
I don't like the name it's non obvious, i think it's ok to have "curve" in inner variable names, maybe not in env-var and options. ; should we also trim(), the value of environ.get, or be stricter on it's format ?
There was a problem hiding this comment.
I agree, I think we could hide "curve" here as an implementation detail; an argument for keeping it as-is would be alignment with ipyparallel (ipython/ipyparallel#553).
I think an obvious choice would be enable_transport_encryption?
Same change would need to follow in jupyter-server/jupyter_server#1638.
CC @minrk in case if you have an opinion here
There was a problem hiding this comment.
enable_transport_encryption / JUPYTER_ENABLE_TRANSPORT_ENCRYPTION seems fine to me, if a bit verbose. I can update ipyparallel to match, no big deal.
Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
Co-authored-by: Min RK <benjaminrk@gmail.com>
|
I kicked test; everything passing. Do you want to update the PR description extensively before merge ? |
krassowski
left a comment
There was a problem hiding this comment.
The PR description is fine, but we should release jupyter-client and update pyproject.toml before we merge
This commit adds CurveZMQ transport encryption to jupyter_client, providing the foundational layer for encrypted kernel communication. It is the upstream dependency for ipykernel#1515 and jupyter-server#1638. What's changed - local_provisioner.py: Generates a CurveZMQ keypair and writes curve_publickey / curve_secretkey into the connection file. The client owns key generation. - connect.py: Reads curve keys from connection files and applies them when setting up ZMQ sockets. - manager.py: Introduces a transport_encryption traitlet with three modes: - 'disabled' (default) — no encryption, existing behavior unchanged - 'auto' — enables encryption only for kernelspecs that advertise metadata.supported_encryption: 'curve' - 'required' — encryption is mandatory; kernel startup fails if the kernelspec doesn't declare support - channels.py / client.py: Heartbeat channel configured as a CurveZMQ client using the server's public key. - Validation: Checks for libsodium support in pyzmq at startup and raises a clear error if missing. Design notes - Named `transport_encryption` (not a boolean) to leave room for future encryption backends beyond CurveZMQ. - Fully backward-compatible: 'disabled' is the default, so nothing changes for existing kernels. - Kernel capability discovery is via kernelspec metadata (supported_encryption: 'curve'), handled on the kernel side in ipykernel#1515. - Guards against pyzmq builds without libsodium, with graceful degradation or a clear error depending on the configured mode. ### References - Closes #808 - PoC for jupyter/enhancement-proposals#75 - Sibling PR ipython/ipykernel#1515 - Toggle on server-level: jupyter-server/jupyter_server#1638
|
All tests pass 🎉 I do not have merge rights here, can we get this merged and released? |
This PR adds support for ZMQ Curve cryptography to encrypt kernel communications over TCP, addressing the current limitation of all code and outputs being transmitted in plaintext.
What's changed
curve_publickey/curve_secretkeyfrom connection files and applies them to all ZMQ sockets (iopub,shell,control,stdin,heartbeat) via new_apply_curve_server_options()/_apply_curve_client_options()helpers."supported_encryption": "curve"so frontends can discover and negotiate encryption capability.References
Code changes