#!/usr/bin/env python # # gstfsd - WebVirtCloud daemon for managing VM's filesystem # import SocketServer import json import guestfs import re import os from jwcrypto import jws, jwk, jwe PORT = 16510 ADDRESS = "0.0.0.0" SECRET = None class MyTCPServer(SocketServer.ThreadingTCPServer): allow_reuse_address = True class MyTCPServerHandler(SocketServer.BaseRequestHandler): def handle(self): # recive data and check authentcation try: signed_data = jws.JWS() signed_data.deserialize(self.request.recv(4096).strip()) signed_data.verify(SECRET, "HS512") encrypted_data = jwe.JWE(algs=["A256KW", "A256CBC-HS512"]) encrypted_data.deserialize(signed_data.payload) encrypted_data.decrypt(SECRET) data = json.loads(encrypted_data.plaintext) # GuestFS gfs = guestfs.GuestFS(python_return_dict=True) gfs.add_domain(data['vname']) gfs.launch() parts = gfs.list_partitions() for part in parts: try: gfs.mount(part, '/') if gfs.is_file('/etc/shadow'): if data['action'] == 'password': file_shadow = gfs.cat('/etc/shadow') new_root_hash = "root:" + data['passwd'] + ":" file_shadow_new = re.sub('^root:.*?:', new_root_hash, file_shadow) gfs.write('/etc/shadow', file_shadow_new) gfs.chmod(640, '/etc/shadow') self.request.sendall(json.dumps({'return': 'success'})) if data['action'] == 'publickey': if not gfs.is_dir('/root/.ssh'): gfs.mkdir('/root/.ssh') gfs.chmod(0700, "/root/.ssh") gfs.write('/root/.ssh/authorized_keys', data['key']) gfs.chmod(0600, '/root/.ssh/authorized_keys') self.request.sendall(json.dumps({'return': 'success'})) gfs.umount(part) except RuntimeError: pass gfs.shutdown() gfs.close() # we check signature before trying to decrypt so jwe.InvalidJWEData should not be raised ever except (jws.InvalidJWSObject, jwe.InvalidJWEData, RuntimeError, ValueError) as err: self.request.sendall(json.dumps({'return': 'error', 'message': err.message})) except jws.InvalidJWSSignature as err: self.request.sendall(json.dumps({'return': 'error', 'message': ( "Fail to verify request signature. Check if you have imported " "the key (/var/lib/gstfsd/SECRET) in WebVirtCloud" )})) if not os.path.isfile("/var/lib/gstfsd/SECRET"): try: os.mkdir("/var/lib/gstfsd") except OSError as error: if error.errno != 17: # File exists raise os.chmod("/var/lib/gstfsd", 0700) with open("/var/lib/gstfsd/SECRET", 'w') as f: f.write(jwk.JWK(generate='oct', size=256).export()) os.chmod("/var/lib/gstfsd/SECRET", 0600) with open("/var/lib/gstfsd/SECRET") as f: SECRET = jwk.JWK(**json.load(f)) server = MyTCPServer((ADDRESS, PORT), MyTCPServerHandler) server.serve_forever()