{
  "__type": "IngestedDoc",
  "__tag": 4010,
  "_content": {},
  "_ordered_sections": [],
  "item_file": null,
  "item_line": null,
  "item_type": null,
  "aliases": [],
  "example_section_data": {
    "__type": "Section",
    "__tag": 4015,
    "children": [],
    "title": [],
    "level": 0,
    "target": null
  },
  "see_also": [],
  "signature": null,
  "references": null,
  "qa": "security",
  "arbitrary": [
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "versionadded",
          "base_type": "neutral",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "versionadded 8.9"
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "By default, the ZMQ sockets used to communicate with kernels (shell, IOPub, stdin, control, heartbeat) are bound to local TCP ports with no transport-level encryption. Any process on the same host that can reach those ports can connect and read messages, including all IOPub output."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Link",
              "__tag": 4049,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "CurveZMQ"
                }
              ],
              "url": "https://rfc.zeromq.org/spec/26/",
              "title": ""
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " adds elliptic-curve encryption and authentication at the ZMQ transport layer. When enabled, the "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "KernelManager"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " generates a keypair, writes it into the kernel's connection file, and configures all sockets as a CurveZMQ server. Clients must present the correct server public key to connect; unauthenticated connections are silently dropped before any data is delivered."
            }
          ]
        },
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "note",
          "base_type": "note",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "note "
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "CurveZMQ is only available when pyzmq was compiled against a libzmq that includes libsodium. You can verify this with      "
                }
              ]
            },
            {
              "__type": "Code",
              "__tag": 4050,
              "value": "python -c \"import zmq; print(zmq.has('curve'))\"",
              "execution_status": null,
              "out": ""
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "If this prints "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "False"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": ", the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "transport_encryption"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " setting has no effect and attempts to set it to "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "'auto'"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " or "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "'required'"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " will raise a "
                },
                {
                  "__type": "CrossRef",
                  "__tag": 4002,
                  "value": "traitlets.TraitError",
                  "reference": {
                    "__type": "RefInfo",
                    "__tag": 4000,
                    "module": "traitlets",
                    "version": "?",
                    "kind": "module",
                    "path": "traitlets.traitlets:TraitError"
                  },
                  "kind": "module"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "."
                }
              ]
            }
          ]
        },
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "note",
          "base_type": "note",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "note "
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "transport_encryption"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " applies to both the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "tcp"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " and "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "ipc"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " transports. IPC sockets also rely on filesystem permissions for access control, but CurveZMQ can be layered on top for defense in depth."
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Transport security for kernels"
        }
      ],
      "level": 0,
      "target": "security"
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Transport encryption is controlled by the "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "KernelManager.transport_encryption"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " traitlet, which accepts three values:"
            }
          ]
        },
        {
          "__type": "DefList",
          "__tag": 4033,
          "children": [
            {
              "__type": "DefListItem",
              "__tag": 4037,
              "dt": {
                "__type": "Paragraph",
                "__tag": 4045,
                "children": [
                  {
                    "__type": "InlineCode",
                    "__tag": 4051,
                    "value": "'disabled'"
                  },
                  {
                    "__type": "Text",
                    "__tag": 4046,
                    "value": " (default)"
                  }
                ]
              },
              "dd": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "No CurveZMQ keys are generated. All kernel sockets are unencrypted."
                    }
                  ]
                }
              ]
            },
            {
              "__type": "DefListItem",
              "__tag": 4037,
              "dt": {
                "__type": "Paragraph",
                "__tag": 4045,
                "children": [
                  {
                    "__type": "InlineCode",
                    "__tag": 4051,
                    "value": "'auto'"
                  }
                ]
              },
              "dd": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Keys are generated "
                    },
                    {
                      "__type": "Strong",
                      "__tag": 4048,
                      "children": [
                        {
                          "__type": "Text",
                          "__tag": 4046,
                          "value": "only when the kernelspec declares support"
                        }
                      ]
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": " via     "
                    },
                    {
                      "__type": "InlineCode",
                      "__tag": 4051,
                      "value": "metadata.supported_encryption: ['curve']"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": ". Kernelspecs that do not     declare this field are started without encryption, so the setting is safe     to enable globally without breaking existing kernels."
                    }
                  ]
                }
              ]
            },
            {
              "__type": "DefListItem",
              "__tag": 4037,
              "dt": {
                "__type": "Paragraph",
                "__tag": 4045,
                "children": [
                  {
                    "__type": "InlineCode",
                    "__tag": 4051,
                    "value": "'required'"
                  }
                ]
              },
              "dd": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Keys are always generated. Startup fails with a "
                    },
                    {
                      "__type": "CrossRef",
                      "__tag": 4002,
                      "value": "RuntimeError",
                      "reference": {
                        "__type": "RefInfo",
                        "__tag": 4000,
                        "module": "builtins",
                        "version": "?",
                        "kind": "module",
                        "path": "builtins:RuntimeError"
                      },
                      "kind": "module"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": " if     the kernelspec does not declare "
                    },
                    {
                      "__type": "InlineCode",
                      "__tag": 4051,
                      "value": "metadata.supported_encryption: ['curve']"
                    },
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": ",     so kernels that have not been updated to handle the connection-file keys     are never started unencrypted."
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To enable encryption for all kernels that support it, add the following to your configuration:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "c.KernelManager.transport_encryption = \"auto\"",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "To enforce encryption and refuse to start kernels that do not declare support:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "c.KernelManager.transport_encryption = \"required\"",
          "execution_status": null,
          "out": ""
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "The "
        },
        {
          "__type": "InlineCode",
          "__tag": 4051,
          "value": "transport_encryption"
        },
        {
          "__type": "Text",
          "__tag": 4046,
          "value": " setting"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "A kernel must declare CurveZMQ support in its "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "kernel.json"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " before the "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "KernelManager"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " will provision keys for it:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "{\n    \"argv\": [\"python\", \"-m\", \"ipykernel_launcher\", \"-f\", \"{connection_file}\"],\n    \"display_name\": \"Python 3\",\n    \"language\": \"python\",\n    \"metadata\": {\n        \"supported_encryption\": [\"curve\"]\n    }\n}",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "When "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "transport_encryption"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "'auto'"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", kernelspecs without this field are started normally without encryption. When it is "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "'required'"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", their startup is refused."
            }
          ]
        },
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "note",
          "base_type": "note",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "note "
                }
              ]
            },
            {
              "__type": "Paragraph",
              "__tag": 4045,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "When updating a previously installed kernel to a version that supports encryption you may need to re-install the kernelspec or manually add the "
                },
                {
                  "__type": "InlineCode",
                  "__tag": 4051,
                  "value": "supported_encryption"
                },
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": " metadata field. If you subsequently decide to downgrade, you will need to remove this field as otherwise the kernel will silently fail to connect."
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Kernelspec requirements"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "When "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "transport_encryption"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " is active the connection file written to disk will contain two additional fields alongside the usual port and key fields:"
            }
          ]
        },
        {
          "__type": "DefList",
          "__tag": 4033,
          "children": [
            {
              "__type": "DefListItem",
              "__tag": 4037,
              "dt": {
                "__type": "Paragraph",
                "__tag": 4045,
                "children": [
                  {
                    "__type": "InlineCode",
                    "__tag": 4051,
                    "value": "curve_publickey"
                  }
                ]
              },
              "dd": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Z85-encoded 40-character ASCII string holding the server's CurveZMQ     public key."
                    }
                  ]
                }
              ]
            },
            {
              "__type": "DefListItem",
              "__tag": 4037,
              "dt": {
                "__type": "Paragraph",
                "__tag": 4045,
                "children": [
                  {
                    "__type": "InlineCode",
                    "__tag": 4051,
                    "value": "curve_secretkey"
                  }
                ]
              },
              "dd": [
                {
                  "__type": "Paragraph",
                  "__tag": 4045,
                  "children": [
                    {
                      "__type": "Text",
                      "__tag": 4046,
                      "value": "Z85-encoded 40-character ASCII string holding the server's CurveZMQ     secret key."
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Kernel implementations must read these fields from the connection file and apply them to their ZMQ sockets before binding. See "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "kernels",
              "reference": {
                "__type": "LocalRef",
                "__tag": 4022,
                "kind": "docs",
                "path": "kernels"
              },
              "kind": "exists"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " for the full description of the connection file format."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Connection file fields"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "A kernel that wants to be compatible with "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "transport_encryption"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " must apply the keypair to every socket it binds. In Python, using pyzmq, that looks like:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "import json\nimport zmq\n\nwith open(connection_file_path) as f:\n    cfg = json.load(f)\n\nctx = zmq.Context()\nshell = ctx.socket(zmq.ROUTER)\n\nif \"curve_publickey\" in cfg and \"curve_secretkey\" in cfg:\n    shell.curve_secretkey = cfg[\"curve_secretkey\"].encode()\n    shell.curve_publickey = cfg[\"curve_publickey\"].encode()\n    shell.curve_server = True\n\nshell.bind(f\"tcp://{cfg['ip']}:{cfg['shell_port']}\")",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The same pattern applies to the IOPub, stdin, control, and heartbeat sockets. Setting "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "curve_server = True"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " on a bound socket causes ZMQ to require CurveZMQ authentication on every incoming connection; unauthenticated clients are rejected automatically."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Kernels based on "
            },
            {
              "__type": "Link",
              "__tag": 4049,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "ipykernel"
                }
              ],
              "url": "https://ipykernel.readthedocs.io/",
              "title": ""
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " v7.3+ handle this automatically when the connection file contains the curve fields."
            }
          ]
        },
        {
          "__type": "Admonition",
          "__tag": 4056,
          "kind": "seealso",
          "base_type": "note",
          "children": [
            {
              "__type": "AdmonitionTitle",
              "__tag": 4055,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "seealso "
                }
              ]
            },
            {
              "__type": "DefList",
              "__tag": 4033,
              "children": [
                {
                  "__type": "DefListItem",
                  "__tag": 4037,
                  "dt": {
                    "__type": "Paragraph",
                    "__tag": 4045,
                    "children": [
                      {
                        "__type": "CrossRef",
                        "__tag": 4002,
                        "value": "kernels",
                        "reference": {
                          "__type": "LocalRef",
                          "__tag": 4022,
                          "kind": "docs",
                          "path": "kernels"
                        },
                        "kind": "exists"
                      }
                    ]
                  },
                  "dd": [
                    {
                      "__type": "Paragraph",
                      "__tag": 4045,
                      "children": [
                        {
                          "__type": "Text",
                          "__tag": 4046,
                          "value": "Connection file format and kernelspec reference."
                        }
                      ]
                    }
                  ]
                },
                {
                  "__type": "DefListItem",
                  "__tag": 4037,
                  "dt": {
                    "__type": "Paragraph",
                    "__tag": 4045,
                    "children": [
                      {
                        "__type": "CrossRef",
                        "__tag": 4002,
                        "value": "provisioning",
                        "reference": {
                          "__type": "LocalRef",
                          "__tag": 4022,
                          "kind": "docs",
                          "path": "provisioning"
                        },
                        "kind": "exists"
                      }
                    ]
                  },
                  "dd": [
                    {
                      "__type": "Paragraph",
                      "__tag": 4045,
                      "children": [
                        {
                          "__type": "Text",
                          "__tag": 4046,
                          "value": "How "
                        },
                        {
                          "__type": "InlineCode",
                          "__tag": 4051,
                          "value": "LocalProvisioner"
                        },
                        {
                          "__type": "Text",
                          "__tag": 4046,
                          "value": " generates and injects curve keys during   kernel startup."
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Implementing curve support in a kernel"
        }
      ],
      "level": 1,
      "target": null
    }
  ],
  "local_refs": []
}