mirror of
https://github.com/retspen/webvirtcloud
synced 2026-03-23 11:04:49 +00:00
Use JSON Web Signature and Encryption (JWS & JWE) between webvirtcloud and gstfsd
This commit is contained in:
parent
17cb7ace88
commit
6dc7473ab0
9 changed files with 166 additions and 30 deletions
|
|
@ -13,6 +13,8 @@ class ComputeAddTcpForm(forms.Form):
|
||||||
max_length=100)
|
max_length=100)
|
||||||
password = forms.CharField(error_messages={'required': _('No password has been entered')},
|
password = forms.CharField(error_messages={'required': _('No password has been entered')},
|
||||||
max_length=100)
|
max_length=100)
|
||||||
|
gstfsd_key = forms.CharField(max_length=256, required=False)
|
||||||
|
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name']
|
name = self.cleaned_data['name']
|
||||||
|
|
@ -49,6 +51,8 @@ class ComputeAddSshForm(forms.Form):
|
||||||
max_length=100)
|
max_length=100)
|
||||||
login = forms.CharField(error_messages={'required': _('No login has been entered')},
|
login = forms.CharField(error_messages={'required': _('No login has been entered')},
|
||||||
max_length=20)
|
max_length=20)
|
||||||
|
gstfsd_key = forms.CharField(max_length=256, required=False)
|
||||||
|
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name']
|
name = self.cleaned_data['name']
|
||||||
|
|
@ -87,6 +91,8 @@ class ComputeAddTlsForm(forms.Form):
|
||||||
max_length=100)
|
max_length=100)
|
||||||
password = forms.CharField(error_messages={'required': _('No password has been entered')},
|
password = forms.CharField(error_messages={'required': _('No password has been entered')},
|
||||||
max_length=100)
|
max_length=100)
|
||||||
|
gstfsd_key = forms.CharField(max_length=256, required=False)
|
||||||
|
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name']
|
name = self.cleaned_data['name']
|
||||||
|
|
@ -126,6 +132,8 @@ class ComputeEditHostForm(forms.Form):
|
||||||
max_length=100)
|
max_length=100)
|
||||||
password = forms.CharField(max_length=100)
|
password = forms.CharField(max_length=100)
|
||||||
|
|
||||||
|
gstfsd_key = forms.CharField(max_length=256, required=False)
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name']
|
name = self.cleaned_data['name']
|
||||||
have_symbol = re.match('[^a-zA-Z0-9._-]+', name)
|
have_symbol = re.match('[^a-zA-Z0-9._-]+', name)
|
||||||
|
|
@ -150,6 +158,9 @@ class ComputeAddSocketForm(forms.Form):
|
||||||
name = forms.CharField(error_messages={'required': _('No hostname has been entered')},
|
name = forms.CharField(error_messages={'required': _('No hostname has been entered')},
|
||||||
max_length=20)
|
max_length=20)
|
||||||
|
|
||||||
|
gstfsd_key = forms.CharField(max_length=256, required=False)
|
||||||
|
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name']
|
name = self.cleaned_data['name']
|
||||||
have_symbol = re.match('[^a-zA-Z0-9._-]+', name)
|
have_symbol = re.match('[^a-zA-Z0-9._-]+', name)
|
||||||
|
|
|
||||||
19
computes/migrations/0002_compute_gstfsd_key.py
Normal file
19
computes/migrations/0002_compute_gstfsd_key.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('computes', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='compute',
|
||||||
|
name='gstfsd_key',
|
||||||
|
field=models.CharField(max_length=256, null=True, blank=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -7,6 +7,7 @@ class Compute(models.Model):
|
||||||
login = models.CharField(max_length=20)
|
login = models.CharField(max_length=20)
|
||||||
password = models.CharField(max_length=14, blank=True, null=True)
|
password = models.CharField(max_length=14, blank=True, null=True)
|
||||||
type = models.IntegerField()
|
type = models.IntegerField()
|
||||||
|
gstfsd_key = models.CharField(max_length=256, blank=True, null=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.hostname
|
return self.hostname
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,12 @@
|
||||||
<input type="password" name="password" class="form-control" value="{{ compute.password }}">
|
<input type="password" name="password" class="form-control" value="{{ compute.password }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
||||||
|
|
@ -121,6 +127,12 @@
|
||||||
<input type="text" name="login" class="form-control" value="{{ compute.login }}">
|
<input type="text" name="login" class="form-control" value="{{ compute.login }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
||||||
|
|
@ -163,6 +175,12 @@
|
||||||
<input type="password" name="password" class="form-control" value="{{ compute.password }}">
|
<input type="password" name="password" class="form-control" value="{{ compute.password }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
||||||
|
|
@ -187,6 +205,12 @@
|
||||||
<input type="text" name="name" class="form-control" value="{{ compute.name }}" maxlength="20" required pattern="[a-z0-9\.\-_]+">
|
<input type="text" name="name" class="form-control" value="{{ compute.name }}" maxlength="20" required pattern="[a-z0-9\.\-_]+">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
<button type="submit" class="pull-left btn btn-danger" name="host_del">
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,12 @@
|
||||||
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
|
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" placeholder="Gstfsd JSON Web Key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
|
@ -83,6 +89,12 @@
|
||||||
<input type="text" name="login" class="form-control" placeholder="{% trans "Username" %}">
|
<input type="text" name="login" class="form-control" placeholder="{% trans "Username" %}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" placeholder="Gstfsd JSON Web Key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
|
@ -121,6 +133,12 @@
|
||||||
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
|
<input type="password" name="password" class="form-control" placeholder="{% trans "Password" %}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" placeholder="Gstfsd JSON Web Key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
|
@ -141,6 +159,12 @@
|
||||||
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
|
<input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">{% trans "Gstfsd key" %}</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="gstfsd_key" placeholder="Gstfsd JSON Web Key" class="form-control" value="{{ compute.gstfsd_key }}" maxlength="256">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ def computes(request):
|
||||||
'status': connection_manager.host_is_up(compute.type, compute.hostname),
|
'status': connection_manager.host_is_up(compute.type, compute.hostname),
|
||||||
'type': compute.type,
|
'type': compute.type,
|
||||||
'login': compute.login,
|
'login': compute.login,
|
||||||
'password': compute.password
|
'password': compute.password,
|
||||||
|
'gstfsd_key': compute.gstfsd_key
|
||||||
})
|
})
|
||||||
return compute_data
|
return compute_data
|
||||||
|
|
||||||
|
|
@ -66,7 +67,8 @@ def computes(request):
|
||||||
hostname=data['hostname'],
|
hostname=data['hostname'],
|
||||||
type=CONN_TCP,
|
type=CONN_TCP,
|
||||||
login=data['login'],
|
login=data['login'],
|
||||||
password=data['password'])
|
password=data['password'],
|
||||||
|
gstfsd_key=data['gstfsd_key'])
|
||||||
new_tcp_host.save()
|
new_tcp_host.save()
|
||||||
return HttpResponseRedirect(request.get_full_path())
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
else:
|
else:
|
||||||
|
|
@ -79,7 +81,8 @@ def computes(request):
|
||||||
new_ssh_host = Compute(name=data['name'],
|
new_ssh_host = Compute(name=data['name'],
|
||||||
hostname=data['hostname'],
|
hostname=data['hostname'],
|
||||||
type=CONN_SSH,
|
type=CONN_SSH,
|
||||||
login=data['login'])
|
login=data['login'],
|
||||||
|
gstfsd_key=data['gstfsd_key'])
|
||||||
new_ssh_host.save()
|
new_ssh_host.save()
|
||||||
return HttpResponseRedirect(request.get_full_path())
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
else:
|
else:
|
||||||
|
|
@ -93,7 +96,8 @@ def computes(request):
|
||||||
hostname=data['hostname'],
|
hostname=data['hostname'],
|
||||||
type=CONN_TLS,
|
type=CONN_TLS,
|
||||||
login=data['login'],
|
login=data['login'],
|
||||||
password=data['password'])
|
password=data['password'],
|
||||||
|
gstfsd_key=data['gstfsd_key'])
|
||||||
new_tls_host.save()
|
new_tls_host.save()
|
||||||
return HttpResponseRedirect(request.get_full_path())
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
else:
|
else:
|
||||||
|
|
@ -107,7 +111,8 @@ def computes(request):
|
||||||
hostname='localhost',
|
hostname='localhost',
|
||||||
type=CONN_SOCKET,
|
type=CONN_SOCKET,
|
||||||
login='',
|
login='',
|
||||||
password='')
|
password='',
|
||||||
|
gstfsd_key=data['gstfsd_key'])
|
||||||
new_socket_host.save()
|
new_socket_host.save()
|
||||||
return HttpResponseRedirect(request.get_full_path())
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
else:
|
else:
|
||||||
|
|
@ -122,6 +127,7 @@ def computes(request):
|
||||||
compute_edit.hostname = data['hostname']
|
compute_edit.hostname = data['hostname']
|
||||||
compute_edit.login = data['login']
|
compute_edit.login = data['login']
|
||||||
compute_edit.password = data['password']
|
compute_edit.password = data['password']
|
||||||
|
compute_edit.gstfsd_key = data['gstfsd_key']
|
||||||
compute_edit.save()
|
compute_edit.save()
|
||||||
return HttpResponseRedirect(request.get_full_path())
|
return HttpResponseRedirect(request.get_full_path())
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ import SocketServer
|
||||||
import json
|
import json
|
||||||
import guestfs
|
import guestfs
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
|
from jwcrypto import jws, jwk, jwe
|
||||||
|
|
||||||
PORT = 16510
|
PORT = 16510
|
||||||
ADDRESS = "0.0.0.0"
|
ADDRESS = "0.0.0.0"
|
||||||
|
SECRET = None
|
||||||
|
|
||||||
|
|
||||||
class MyTCPServer(SocketServer.ThreadingTCPServer):
|
class MyTCPServer(SocketServer.ThreadingTCPServer):
|
||||||
|
|
@ -19,12 +21,20 @@ class MyTCPServer(SocketServer.ThreadingTCPServer):
|
||||||
|
|
||||||
class MyTCPServerHandler(SocketServer.BaseRequestHandler):
|
class MyTCPServerHandler(SocketServer.BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
# recive data
|
# recive data and check authentcation
|
||||||
data = json.loads(self.request.recv(1024).strip())
|
|
||||||
|
|
||||||
# GuestFS
|
|
||||||
gfs = guestfs.GuestFS(python_return_dict=True)
|
|
||||||
try:
|
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.add_domain(data['vname'])
|
||||||
gfs.launch()
|
gfs.launch()
|
||||||
parts = gfs.list_partitions()
|
parts = gfs.list_partitions()
|
||||||
|
|
@ -51,8 +61,29 @@ class MyTCPServerHandler(SocketServer.BaseRequestHandler):
|
||||||
pass
|
pass
|
||||||
gfs.shutdown()
|
gfs.shutdown()
|
||||||
gfs.close()
|
gfs.close()
|
||||||
except RuntimeError, err:
|
# 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}))
|
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 = MyTCPServer((ADDRESS, PORT), MyTCPServerHandler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,6 @@ Django==1.8.11
|
||||||
websockify==0.8.0
|
websockify==0.8.0
|
||||||
gunicorn==19.3.0
|
gunicorn==19.3.0
|
||||||
libvirt-python==1.3.2
|
libvirt-python==1.3.2
|
||||||
|
jwcrypto>=0.2.1
|
||||||
#http://github.com/retspen/retspen.github.io/raw/master/libxml2-python-2.9.1.tar.gz
|
#http://github.com/retspen/retspen.github.io/raw/master/libxml2-python-2.9.1.tar.gz
|
||||||
http://git.gnome.org/browse/libxml2/snapshot/libxml2-2.9.1.tar.gz#egg=libxml2-python&subdirectory=python
|
http://git.gnome.org/browse/libxml2/snapshot/libxml2-2.9.1.tar.gz#egg=libxml2-python&subdirectory=python
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import crypt
|
||||||
from string import letters, digits
|
from string import letters, digits
|
||||||
from random import choice
|
from random import choice
|
||||||
from bisect import insort
|
from bisect import insort
|
||||||
|
from jwcrypto import jws, jwk, jwe
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
@ -291,17 +292,26 @@ def instance(request, compute_id, vname):
|
||||||
data = {'action': 'password', 'passwd': passwd_hash, 'vname': vname}
|
data = {'action': 'password', 'passwd': passwd_hash, 'vname': vname}
|
||||||
|
|
||||||
if conn.get_status() == 5:
|
if conn.get_status() == 5:
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
if compute.gstfsd_key:
|
||||||
s.connect((compute.hostname, 16510))
|
key = jwk.JWK(**json.loads(compute.gstfsd_key.strip()))
|
||||||
s.send(json.dumps(data))
|
data = jwe.JWE(json.dumps(data), algs=["A256KW", "A256CBC-HS512"])
|
||||||
result = json.loads(s.recv(1024))
|
data.add_recipient(key, header='{"alg":"A256KW","enc":"A256CBC-HS512"}')
|
||||||
s.close()
|
data = jws.JWS(data.serialize())
|
||||||
msg = _("Reset root password")
|
data.add_signature(key, alg="HS512")
|
||||||
addlogmsg(request.user.username, instance.name, msg)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((compute.hostname, 16510))
|
||||||
|
s.send(data.serialize())
|
||||||
|
result = json.loads(s.recv(4096))
|
||||||
|
s.close()
|
||||||
|
msg = _("Reset root password")
|
||||||
|
addlogmsg(request.user.username, instance.name, msg)
|
||||||
|
|
||||||
if result['return'] == 'success':
|
if result['return'] == 'success':
|
||||||
messages.append(msg)
|
messages.append(msg)
|
||||||
|
else:
|
||||||
|
error_messages.append(result.get('message', msg))
|
||||||
else:
|
else:
|
||||||
|
msg = _("Please import the gstfsd key into this compute. It is in /var/lib/gstfsd/SECRET on %s") % compute.name
|
||||||
error_messages.append(msg)
|
error_messages.append(msg)
|
||||||
else:
|
else:
|
||||||
msg = _("Please shutdow down your instance and then try again")
|
msg = _("Please shutdow down your instance and then try again")
|
||||||
|
|
@ -313,17 +323,26 @@ def instance(request, compute_id, vname):
|
||||||
data = {'action': 'publickey', 'key': publickey.keypublic, 'vname': vname}
|
data = {'action': 'publickey', 'key': publickey.keypublic, 'vname': vname}
|
||||||
|
|
||||||
if conn.get_status() == 5:
|
if conn.get_status() == 5:
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
if compute.gstfsd_key:
|
||||||
s.connect((compute.hostname, 16510))
|
key = jwk.JWK(**json.loads(compute.gstfsd_key.strip()))
|
||||||
s.send(json.dumps(data))
|
data = jwe.JWE(json.dumps(data), algs=["A256KW", "A256CBC-HS512"])
|
||||||
result = json.loads(s.recv(1024))
|
data.add_recipient(key, header='{"alg":"A256KW","enc":"A256CBC-HS512"}')
|
||||||
s.close()
|
data = jws.JWS(data.serialize())
|
||||||
msg = _("Installed new ssh public key %s" % publickey.keyname)
|
data.add_signature(key, alg="HS512")
|
||||||
addlogmsg(request.user.username, instance.name, msg)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((compute.hostname, 16510))
|
||||||
|
s.send(data.serialize())
|
||||||
|
result = json.loads(s.recv(4096))
|
||||||
|
s.close()
|
||||||
|
msg = _("Installed new ssh public key %s" % publickey.keyname)
|
||||||
|
addlogmsg(request.user.username, instance.name, msg)
|
||||||
|
|
||||||
if result['return'] == 'success':
|
if result['return'] == 'success':
|
||||||
messages.append(msg)
|
messages.append(msg)
|
||||||
|
else:
|
||||||
|
error_messages.append(result.get('message', msg))
|
||||||
else:
|
else:
|
||||||
|
msg = _("Please import the gstfsd key into this compute. It is in /var/lib/gstfsd/SECRET on %s") % compute.name
|
||||||
error_messages.append(msg)
|
error_messages.append(msg)
|
||||||
else:
|
else:
|
||||||
msg = _("Please shutdow down your instance and then try again")
|
msg = _("Please shutdow down your instance and then try again")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue