From: "Max R. Carrara" <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v1 master ceph 1/2] provide workaround for PyO3 ImportError
Date: Wed, 16 Jul 2025 19:39:55 +0200 [thread overview]
Message-ID: <20250716173956.980112-2-m.carrara@proxmox.com> (raw)
In-Reply-To: <20250716173956.980112-1-m.carrara@proxmox.com>
By moving the self-signed cert generation into a separate module and
consequently running it via `subprocess.run`--so, as a new,
independent Python process--the PyO3 ImportError is successfully
avoided.
Inspired by an upstream PR [0].
[0]: https://github.com/ceph/ceph/pull/62951
Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
---
...ul-provide-workaround-for-PyO3-Impor.patch | 152 ++++++++++++++++++
patches/series | 1 +
2 files changed, 153 insertions(+)
create mode 100644 patches/0058-pybind-mgr-restful-provide-workaround-for-PyO3-Impor.patch
diff --git a/patches/0058-pybind-mgr-restful-provide-workaround-for-PyO3-Impor.patch b/patches/0058-pybind-mgr-restful-provide-workaround-for-PyO3-Impor.patch
new file mode 100644
index 0000000000..25fb720410
--- /dev/null
+++ b/patches/0058-pybind-mgr-restful-provide-workaround-for-PyO3-Impor.patch
@@ -0,0 +1,152 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Max R. Carrara" <m.carrara@proxmox.com>
+Date: Wed, 16 Jul 2025 13:14:39 +0200
+Subject: [PATCH 58/59] pybind/mgr/restful: provide workaround for PyO3
+ ImportError
+
+Move the self-signed cert generation into a separate module
+inside python-common/ceph and run the module in a separate Python
+process.
+
+This provides a workaround for the ImportError thrown by PyO3 when
+the `restful` module is loaded in the context of multiple Python
+sub-interpreters being present. In particular, the ImportError is
+thrown by the `crypto` module of the `OpenSSL` package.
+
+Inspired by an upstream PR [0].
+
+[0]: https://github.com/ceph/ceph/pull/62951
+
+Signed-off-by: Max R. Carrara <m.carrara@proxmox.com>
+---
+ src/pybind/mgr/restful/module.py | 24 +++------
+ src/python-common/ceph/_crypto_wrap.py | 69 ++++++++++++++++++++++++++
+ 2 files changed, 76 insertions(+), 17 deletions(-)
+ create mode 100644 src/python-common/ceph/_crypto_wrap.py
+
+diff --git a/src/pybind/mgr/restful/module.py b/src/pybind/mgr/restful/module.py
+index 0f8c78e0bd8..7f93c41f1e6 100644
+--- a/src/pybind/mgr/restful/module.py
++++ b/src/pybind/mgr/restful/module.py
+@@ -7,6 +7,7 @@ import json
+ import time
+ import errno
+ import inspect
++import subprocess
+ import tempfile
+ import threading
+ import traceback
+@@ -19,7 +20,6 @@ from . import context
+
+ from uuid import uuid4
+ from pecan import jsonify, make_app
+-from OpenSSL import crypto
+ from pecan.rest import RestController
+ from werkzeug.serving import make_server, make_ssl_devcert
+
+@@ -401,24 +401,14 @@ class Module(MgrModule):
+
+
+ def create_self_signed_cert(self):
+- # create a key pair
+- pkey = crypto.PKey()
+- pkey.generate_key(crypto.TYPE_RSA, 2048)
+-
+- # create a self-signed cert
+- cert = crypto.X509()
+- cert.get_subject().O = "IT"
+- cert.get_subject().CN = "ceph-restful"
+- cert.set_serial_number(int(uuid4()))
+- cert.gmtime_adj_notBefore(0)
+- cert.gmtime_adj_notAfter(10*365*24*60*60)
+- cert.set_issuer(cert.get_subject())
+- cert.set_pubkey(pkey)
+- cert.sign(pkey, 'sha512')
++ cmd = ["python3", "-m", "ceph._crypto_wrap", "create_self_signed_cert"]
++
++ response = subprocess.run(cmd, capture_output=True, check=True)
++ response_obj = json.loads(response.stdout)
+
+ return (
+- crypto.dump_certificate(crypto.FILETYPE_PEM, cert),
+- crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
++ response_obj["cert"].encode("utf-8"),
++ response_obj["key"].encode("utf-8"),
+ )
+
+
+diff --git a/src/python-common/ceph/_crypto_wrap.py b/src/python-common/ceph/_crypto_wrap.py
+new file mode 100644
+index 00000000000..16a19a5345e
+--- /dev/null
++++ b/src/python-common/ceph/_crypto_wrap.py
+@@ -0,0 +1,69 @@
++"""CLI wrapper for cryptographic functions of the :mod:`restful` module.
++
++To be called via :func:`subprocess.run()` as a workaround for
++:class:`ImportError`s related to PyO3's current lack of sub-interpreter
++support.
++
++Note:
++ Since this module is installed as part of the ``ceph`` package,
++ it should be called like so::
++
++ python3 -m ceph._crypto_wrap create_self_signed_cert
++"""
++
++import argparse
++import sys
++import json
++
++from argparse import Namespace
++from typing import Any
++from uuid import uuid4
++
++from OpenSSL import crypto
++
++
++def _respond(data: dict[str, Any]) -> None:
++ json.dump(data, sys.stdout)
++ sys.stdout.flush()
++
++
++def create_self_signed_cert(args: Namespace) -> None:
++ cert_key_pair = _create_self_signed_cert()
++ _respond(cert_key_pair)
++
++
++def _create_self_signed_cert() -> dict[str, str]:
++ # create a key pair
++ pubkey = crypto.PKey()
++ pubkey.generate_key(crypto.TYPE_RSA, 2048)
++
++ # create a self-signed cert
++ cert = crypto.X509()
++ cert.get_subject().O = "IT"
++ cert.get_subject().CN = "ceph-restful"
++ cert.set_serial_number(int(uuid4()))
++ cert.gmtime_adj_notBefore(0)
++ cert.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60)
++ cert.set_issuer(cert.get_subject())
++ cert.set_pubkey(pubkey)
++ cert.sign(pubkey, "sha512")
++
++ return {
++ "cert": crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode(),
++ "key": crypto.dump_privatekey(crypto.FILETYPE_PEM, pubkey).decode(),
++ }
++
++
++def main() -> None:
++ parser = argparse.ArgumentParser(prog="_crypto_wrap.py")
++ subparsers = parser.add_subparsers(required=True)
++
++ parser_cssc = subparsers.add_parser("create_self_signed_cert")
++ parser_cssc.set_defaults(func=create_self_signed_cert)
++
++ args = parser.parse_args()
++ args.func(args)
++
++
++if __name__ == "__main__":
++ main()
diff --git a/patches/series b/patches/series
index 728a9f935e..ff23f8b640 100644
--- a/patches/series
+++ b/patches/series
@@ -51,3 +51,4 @@
0055-python-common-cryptotools-catch-all-failures-to-read.patch
0056-mgr-cephadm-always-use-the-internal-cryptocaller.patch
0057-mgr-dashboard-add-an-option-to-control-the-dashboard.patch
+0058-pybind-mgr-restful-provide-workaround-for-PyO3-Impor.patch
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-07-16 17:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-16 17:39 [pve-devel] [PATCH v1 master ceph 0/2] Fix Ceph Squid Module Loading Max R. Carrara
2025-07-16 17:39 ` Max R. Carrara [this message]
2025-07-16 17:39 ` [pve-devel] [PATCH v1 master ceph 2/2] mgr: fix errors regarding module imports and NOTIFY_TYPES attributes Max R. Carrara
2025-07-16 20:15 ` [pve-devel] applied-series: [PATCH v1 master ceph 0/2] Fix Ceph Squid Module Loading Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250716173956.980112-2-m.carrara@proxmox.com \
--to=m.carrara@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.