1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-03-23 11:04:49 +00:00
This commit is contained in:
Valentin Samir 2016-10-18 07:25:45 +00:00 committed by GitHub
commit 72d57ebc21
10 changed files with 245 additions and 33 deletions

View file

@ -1,4 +1,5 @@
import re import re
import json
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from computes.models import Compute from computes.models import Compute
@ -13,6 +14,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']
@ -41,6 +44,20 @@ class ComputeAddTcpForm(forms.Form):
return hostname return hostname
raise forms.ValidationError(_('This host is already connected')) raise forms.ValidationError(_('This host is already connected'))
def clean_gstfsd_key(self):
gstfsd_key = self.cleaned_data['gstfsd_key']
try:
data = json.loads(gstfsd_key)
if not isinstance(data, dict):
raise forms.ValidationError(_('Gstfsd key must be a json object'))
if not 'k' in data:
raise forms.ValidationError(_('Gstfsd key must have a "k" field'))
if not 'kty' in data:
raise forms.ValidationError(_('Gstfsd key must have a "kty" field'))
except ValueError:
raise forms.ValidationError(_('Gstfsd key must be a valid json'))
return gstfsd_key
class ComputeAddSshForm(forms.Form): class ComputeAddSshForm(forms.Form):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, name = forms.CharField(error_messages={'required': _('No hostname has been entered')},
@ -49,6 +66,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']
@ -77,6 +96,20 @@ class ComputeAddSshForm(forms.Form):
return hostname return hostname
raise forms.ValidationError(_('This host is already connected')) raise forms.ValidationError(_('This host is already connected'))
def clean_gstfsd_key(self):
gstfsd_key = self.cleaned_data['gstfsd_key']
try:
data = json.loads(gstfsd_key)
if not isinstance(data, dict):
raise forms.ValidationError(_('Gstfsd key must be a json object'))
if not 'k' in data:
raise forms.ValidationError(_('Gstfsd key must have a "k" field'))
if not 'kty' in data:
raise forms.ValidationError(_('Gstfsd key must have a "kty" field'))
except ValueError:
raise forms.ValidationError(_('Gstfsd key must be a valid json'))
return gstfsd_key
class ComputeAddTlsForm(forms.Form): class ComputeAddTlsForm(forms.Form):
name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, name = forms.CharField(error_messages={'required': _('No hostname has been entered')},
@ -87,6 +120,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']
@ -115,6 +150,20 @@ class ComputeAddTlsForm(forms.Form):
return hostname return hostname
raise forms.ValidationError(_('This host is already connected')) raise forms.ValidationError(_('This host is already connected'))
def clean_gstfsd_key(self):
gstfsd_key = self.cleaned_data['gstfsd_key']
try:
data = json.loads(gstfsd_key)
if not isinstance(data, dict):
raise forms.ValidationError(_('Gstfsd key must be a json object'))
if not 'k' in data:
raise forms.ValidationError(_('Gstfsd key must have a "k" field'))
if not 'kty' in data:
raise forms.ValidationError(_('Gstfsd key must have a "kty" field'))
except ValueError:
raise forms.ValidationError(_('Gstfsd key must be a valid json'))
return gstfsd_key
class ComputeEditHostForm(forms.Form): class ComputeEditHostForm(forms.Form):
host_id = forms.CharField() host_id = forms.CharField()
@ -126,6 +175,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)
@ -145,11 +196,28 @@ class ComputeEditHostForm(forms.Form):
raise forms.ValidationError(_('Wrong IP address')) raise forms.ValidationError(_('Wrong IP address'))
return hostname return hostname
def clean_gstfsd_key(self):
gstfsd_key = self.cleaned_data['gstfsd_key']
try:
data = json.loads(gstfsd_key)
if not isinstance(data, dict):
raise forms.ValidationError(_('Gstfsd key must be a json object'))
if not 'k' in data:
raise forms.ValidationError(_('Gstfsd key must have a "k" field'))
if not 'kty' in data:
raise forms.ValidationError(_('Gstfsd key must have a "kty" field'))
except ValueError:
raise forms.ValidationError(_('Gstfsd key must be a valid json'))
return gstfsd_key
class ComputeAddSocketForm(forms.Form): 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)
@ -162,3 +230,17 @@ class ComputeAddSocketForm(forms.Form):
except Compute.DoesNotExist: except Compute.DoesNotExist:
return name return name
raise forms.ValidationError(_('This host is already connected')) raise forms.ValidationError(_('This host is already connected'))
def clean_gstfsd_key(self):
gstfsd_key = self.cleaned_data['gstfsd_key']
try:
data = json.loads(gstfsd_key)
if not isinstance(data, dict):
raise forms.ValidationError(_('Gstfsd key must be a json object'))
if not 'k' in data:
raise forms.ValidationError(_('Gstfsd key must have a "k" field'))
if not 'kty' in data:
raise forms.ValidationError(_('Gstfsd key must have a "kty" field'))
except ValueError:
raise forms.ValidationError(_('Gstfsd key must be a valid json'))
return gstfsd_key

View 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),
),
]

View file

@ -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

View file

@ -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">

View file

@ -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">

View file

@ -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:

View file

@ -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()

View file

@ -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

View file

@ -245,10 +245,10 @@
</div> </div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="rootpasswd"> <div role="tabpanel" class="tab-pane tab-pane-bordered" id="rootpasswd">
<p>{% trans "You need shut down your instance and enter a new root password." %}</p> <p>{% trans "You need shut down your instance and enter a new root password." %}</p>
<form class="form-inline" method="post" role="form">{% csrf_token %} <form class="form-inline" method="post" role="form" autocomplete="off">{% csrf_token %}
<div class="form-group"> <div class="form-group">
<div class="col-sm-12"> <div class="col-sm-12">
<input type="text" class="form-control input-lg" name="passwd" placeholder="{% trans "Enter Password" %}" maxlength="24"> <input type="text" class="form-control input-lg" name="passwd" placeholder="{% trans "Enter Password" %}" maxlength="24" autocomplete="off">
</div> </div>
</div> </div>
{% ifequal status 5 %} {% ifequal status 5 %}
@ -257,6 +257,7 @@
<button class="btn btn-lg btn-success pull-right disabled">{% trans "Reset Root Password" %}</button> <button class="btn btn-lg btn-success pull-right disabled">{% trans "Reset Root Password" %}</button>
{% endifequal %} {% endifequal %}
</form> </form>
<p>{% trans "An empty password disable the root password." %}</p>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div role="tabpanel" class="tab-pane tab-pane-bordered" id="sshkeys"> <div role="tabpanel" class="tab-pane tab-pane-bordered" id="sshkeys">

View file

@ -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
@ -288,21 +289,34 @@ def instance(request, compute_id, vname):
if 'rootpasswd' in request.POST: if 'rootpasswd' in request.POST:
passwd = request.POST.get('passwd', '') passwd = request.POST.get('passwd', '')
passwd_hash = crypt.crypt(passwd, '$6$kgPoiREy') if passwd:
passwd_hash = crypt.crypt(passwd, '$6$%s' % ''.join([choice(letters + digits) for i in xrange(8)]))
# if password is empty, disable the root password
else:
passwd_hash = "*"
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")
@ -314,17 +328,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")