From 4dc471ed605cd08b35234eac5188459d2a41685b Mon Sep 17 00:00:00 2001 From: Boris Ranto Date: Tue, 20 Jun 2017 18:09:46 -0400 Subject: [PATCH] restful: Introduce create-self-signed-cert command This implements a create-self-signed-cert command for the ceph-mgr restful interface. It is designed so that it will try to restart the module once the cert is created. Signed-off-by: Boris Ranto --- ceph.spec.in | 2 + debian/control | 1 + src/pybind/mgr/restful/module.py | 70 ++++++++++++++++++++++++++++++-- src/vstart.sh | 11 +---- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/ceph.spec.in b/ceph.spec.in index 59751d44624..60d59c52cac 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -325,10 +325,12 @@ Requires: ceph-base = %{_epoch_prefix}%{version}-%{release} %if 0%{?fedora} || 0%{?rhel} Requires: python-cherrypy Requires: python-werkzeug +Requires: pyOpenSSL %endif %if 0%{?suse_version} Requires: python-CherryPy Requires: python-Werkzeug +Requires: python-pyOpenSSL %endif Requires: python-pecan %description mgr diff --git a/debian/control b/debian/control index cc3009f8738..a9ce89021a3 100644 --- a/debian/control +++ b/debian/control @@ -161,6 +161,7 @@ Description: debugging symbols for ceph-mds Package: ceph-mgr Architecture: linux-any Depends: ceph-base (= ${binary:Version}), + python-openssl, python-pecan, python-werkzeug, ${misc:Depends}, diff --git a/src/pybind/mgr/restful/module.py b/src/pybind/mgr/restful/module.py index 07da1ec03a5..12b48ab289d 100644 --- a/src/pybind/mgr/restful/module.py +++ b/src/pybind/mgr/restful/module.py @@ -15,6 +15,7 @@ import common 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 @@ -212,6 +213,11 @@ class Module(MgrModule): "desc": "List all API keys", "perm": "rw" }, + { + "cmd": "restful create-self-signed-cert", + "desc": "Create localized self signed certificate", + "perm": "rw" + }, ] def __init__(self, *args, **kwargs): @@ -227,12 +233,21 @@ class Module(MgrModule): self.server = None + self.stop_server = False + self.serve_event = threading.Event() + def serve(self): - try: - self._serve() - except: - self.log.error(str(traceback.format_exc())) + while not self.stop_server: + try: + self._serve() + self.server.socket.close() + except: + self.log.error(str(traceback.format_exc())) + + # Wait and clear the threading event + self.serve_event.wait() + self.serve_event.clear() def get_localized_config(self, key): r = self.get_config(self.get_mgr_id() + '/' + key) @@ -296,9 +311,21 @@ class Module(MgrModule): def shutdown(self): + try: + self.stop_server = True + if self.server: + self.server.shutdown() + self.serve_event.set() + except: + self.log.error(str(traceback.format_exc())) + raise + + + def restart(self): try: if self.server: self.server.shutdown() + self.serve_event.set() except: self.log.error(str(traceback.format_exc())) @@ -332,6 +359,28 @@ class Module(MgrModule): self.log.debug("Unhandled notification type '%s'" % notify_type) + 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') + + return ( + crypto.dump_certificate(crypto.FILETYPE_PEM, cert), + crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey) + ) + + def handle_command(self, command): self.log.warn("Handling command: '%s'" % str(command)) if command['prefix'] == "restful create-key": @@ -368,6 +417,19 @@ class Module(MgrModule): "", ) + elif command['prefix'] == "restful create-self-signed-cert": + cert, pkey = self.create_self_signed_cert() + + self.set_config(self.get_mgr_id() + '/crt', cert) + self.set_config(self.get_mgr_id() + '/key', pkey) + + self.restart() + return ( + 0, + "Restarting RESTful API server...", + "" + ) + else: return ( -errno.EINVAL, diff --git a/src/vstart.sh b/src/vstart.sh index bfc07a9f26c..f796a3c721a 100755 --- a/src/vstart.sh +++ b/src/vstart.sh @@ -639,16 +639,8 @@ EOF DASH_URLS+="http://$IP:$MGR_PORT/" MGR_PORT=$(($MGR_PORT + 1000)) - CERT=`mktemp` - PKEY=`mktemp` - openssl req -new -nodes -x509 \ - -subj "/O=IT/CN=ceph-mgr-restful" \ - -days 3650 -keyout "$PKEY" -out "$CERT" -extensions v3_ca ceph_adm config-key put mgr/restful/$name/server_addr $IP ceph_adm config-key put mgr/restful/$name/server_port $MGR_PORT - ceph_adm config-key put mgr/restful/$name/crt -i $CERT - ceph_adm config-key put mgr/restful/$name/key -i $PKEY - rm $CERT $PKEY RESTFUL_URLS+="https://$IP:$MGR_PORT" MGR_PORT=$(($MGR_PORT + 1000)) @@ -658,7 +650,8 @@ EOF done SF=`mktemp` - ceph_adm tell mgr.x restful create-key admin -o $SF + ceph_adm tell mgr restful create-self-signed-cert + ceph_adm tell mgr restful create-key admin -o $SF RESTFUL_SECRET=`cat $SF` rm $SF } -- 2.39.5