mirror of
https://github.com/retspen/webvirtcloud
synced 2026-03-23 11:04:49 +00:00
89 lines
3.3 KiB
Python
89 lines
3.3 KiB
Python
#!/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()
|