]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
restful: Introduce create-self-signed-cert command
authorBoris Ranto <branto@redhat.com>
Tue, 20 Jun 2017 22:09:46 +0000 (18:09 -0400)
committerSage Weil <sage@redhat.com>
Wed, 21 Jun 2017 16:32:49 +0000 (12:32 -0400)
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 <branto@redhat.com>
ceph.spec.in
debian/control
src/pybind/mgr/restful/module.py
src/vstart.sh

index 59751d4462472e1cda71b5de914b9362785ffb38..60d59c52cac22c9c39ecbafd930f2bb26d9d551d 100644 (file)
@@ -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
index cc3009f873831b86d2e33c5bac9e629fa5ae5299..a9ce89021a321d44d7abb1152a3c3b2322ecc907 100644 (file)
@@ -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},
index 07da1ec03a53b24296744ef6fc9a1e2a77af1113..12b48ab289d9c20b91cc6553b4006658fe229e94 100644 (file)
@@ -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,
index bfc07a9f26cfafcd69d38729237e5789f8198488..f796a3c721a8e71bf7c626c66c582f1f5ba023d4 100755 (executable)
@@ -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
 }