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
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