[PATCH] Set default storage pool to autostart and make persistent
by Christy Perez
The default storage pool wasn't set to autostart, and wasn't
persistent. If a user wants to continue to use any VMs they
have created in kimchi (maybe only for troubleshooting) but
kimchi isn't active, the default pool may not be active.
Signed-off-by: Christy Perez <christy(a)linux.vnet.ibm.com>
---
src/kimchi/model/model.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/model/model.py b/src/kimchi/model/model.py
index a7d843e..a766ca5 100644
--- a/src/kimchi/model/model.py
+++ b/src/kimchi/model/model.py
@@ -71,7 +71,8 @@ class Model(BaseModel):
pool = conn.storagePoolLookupByName("default")
except libvirt.libvirtError:
try:
- pool = conn.storagePoolCreateXML(xml, 0)
+ pool = conn.storagePoolDefineXML(xml, 0)
+ pool.setAutostart(1)
except libvirt.libvirtError, e:
cherrypy.log.error("Fatal: Cannot create default pool because "
"of %s, exit kimchid" % e.message,
--
1.9.0
10 years, 8 months
[PATCH v2] Enable encryption in vm console connection
by Mark Wu
The current vm ui console connection is unencrypted. This patch enables
encrypted vm console connection. But browsers doesn't
support well for the usage self-signed certs in the ssl websocket
connection. For details, please see:
https://github.com/kanaka/websockify/wiki/Encrypted-Connections
For chrome browser, the encrypted console connection should work after
you login with ssl connection. But for firefox, you have to connect to
https://host-ip:64667/ and accept the self-signed cert.
---
src/kimchi/vnc.py | 10 ++++++++--
ui/js/src/kimchi.api.js | 2 ++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/vnc.py b/src/kimchi/vnc.py
index 1f36e9a..3251f06 100644
--- a/src/kimchi/vnc.py
+++ b/src/kimchi/vnc.py
@@ -23,7 +23,7 @@ import os
import subprocess
-from kimchi.config import config
+from kimchi.config import config, paths
WS_TOKENS_DIR = '/var/lib/kimchi/vnc-tokens'
@@ -36,9 +36,15 @@ def new_ws_proxy():
if e.errno == errno.EEXIST:
pass
+ cert = config.get('server', 'ssl_cert')
+ key = config.get('server', 'ssl_key')
+ if not (cert and key):
+ cert = '%s/kimchi-cert.pem' % paths.conf_dir
+ key = '%s/kimchi-key.pem' % paths.conf_dir
+
cmd = os.path.join(os.path.dirname(__file__), 'websockify.py')
args = ['python', cmd, config.get('display', 'display_proxy_port'),
- '--target-config', WS_TOKENS_DIR]
+ '--target-config', WS_TOKENS_DIR, '--cert', cert, '--key', key]
p = subprocess.Popen(args, close_fds=True)
return p
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 1bde45c..6fcac6d 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -332,6 +332,7 @@ var kimchi = {
url = 'http://' + location.hostname + ':' + http_port;
url += "/vnc_auto.html?port=" + proxy_port;
url += "&path=?token=" + encodeURIComponent(vm);
+ url += '&encrypt=1'
window.open(url);
});
}).error(function() {
@@ -355,6 +356,7 @@ var kimchi = {
url = 'http://' + location.hostname + ':' + http_port;
url += "/spice.html?port=" + proxy_port + "&listen="
+ data.graphics.listen + "&token=" + encodeURIComponent(vm);
+ url += '&encrypt=1'
window.open(url);
});
}).error(function() {
--
1.8.4.2
10 years, 8 months
[PATCH] Add encrypted vm console connection
by Mark Wu
The current vm ui console connection is unencrypted. This patch adds
encrypted vm console connection by enabling ssl support in websockify
and adding a new connection option on UI side. We don't enable the
encrypted by default in the existing vm console connection because it
can avoid the overhead caused by encryption and also browsers doesn't
support well for the usage self-signed certs in the ssl websocket
connection. For details, please see:
https://github.com/kanaka/websockify/wiki/Encrypted-Connections
For chrome browser, the encrypted console connection should work after
you login with ssl connection. But for firefox, you have to connect to
https://host-ip:64667/ and accept the self-signed cert.
---
src/kimchi/vnc.py | 10 ++++++++--
ui/js/src/kimchi.api.js | 8 +++++++-
ui/js/src/kimchi.guest_main.js | 20 ++++++++++++++++++--
ui/pages/guest.html.tmpl | 1 +
4 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/src/kimchi/vnc.py b/src/kimchi/vnc.py
index 1f36e9a..3251f06 100644
--- a/src/kimchi/vnc.py
+++ b/src/kimchi/vnc.py
@@ -23,7 +23,7 @@ import os
import subprocess
-from kimchi.config import config
+from kimchi.config import config, paths
WS_TOKENS_DIR = '/var/lib/kimchi/vnc-tokens'
@@ -36,9 +36,15 @@ def new_ws_proxy():
if e.errno == errno.EEXIST:
pass
+ cert = config.get('server', 'ssl_cert')
+ key = config.get('server', 'ssl_key')
+ if not (cert and key):
+ cert = '%s/kimchi-cert.pem' % paths.conf_dir
+ key = '%s/kimchi-key.pem' % paths.conf_dir
+
cmd = os.path.join(os.path.dirname(__file__), 'websockify.py')
args = ['python', cmd, config.get('display', 'display_proxy_port'),
- '--target-config', WS_TOKENS_DIR]
+ '--target-config', WS_TOKENS_DIR, '--cert', cert, '--key', key]
p = subprocess.Popen(args, close_fds=True)
return p
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 1bde45c..262f64d 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -312,7 +312,7 @@ var kimchi = {
});
},
- vncToVM : function(vm) {
+ vncToVM : function(vm, encrypted) {
kimchi.requestJSON({
url : '/config',
type : 'GET',
@@ -332,6 +332,9 @@ var kimchi = {
url = 'http://' + location.hostname + ':' + http_port;
url += "/vnc_auto.html?port=" + proxy_port;
url += "&path=?token=" + encodeURIComponent(vm);
+ if (encrypted) {
+ url += '&encrypt=1'
+ }
window.open(url);
});
}).error(function() {
@@ -355,6 +358,9 @@ var kimchi = {
url = 'http://' + location.hostname + ':' + http_port;
url += "/spice.html?port=" + proxy_port + "&listen="
+ data.graphics.listen + "&token=" + encodeURIComponent(vm);
+ if (encrypted) {
+ url += '&encrypt=1'
+ }
window.open(url);
});
}).error(function() {
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index 510e7f9..a811a6b 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -151,10 +151,22 @@ kimchi.openVmConsole = function(event) {
var vm=$(this).closest('li[name=guest]');
var vmObject=vm.data();
if (vmObject.graphics['type'] == 'vnc') {
- kimchi.vncToVM(vm.attr('id'));
+ kimchi.vncToVM(vm.attr('id'), false);
}
else if (vmObject.graphics['type'] == 'spice') {
- kimchi.spiceToVM(vm.attr('id'));
+ kimchi.spiceToVM(vm.attr('id'), false);
+ }
+
+};
+
+kimchi.openVmSecureConsole = function(event) {
+ var vm=$(this).closest('li[name=guest]');
+ var vmObject=vm.data();
+ if (vmObject.graphics['type'] == 'vnc') {
+ kimchi.vncToVM(vm.attr('id'), true);
+ }
+ else if (vmObject.graphics['type'] == 'spice') {
+ kimchi.spiceToVM(vm.attr('id'), true);
}
};
@@ -275,13 +287,17 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
}
var consoleActions=guestActions.find("[name=vm-console]");
+ var secureConsoleActions=guestActions.find("[name=vm-secureConsole]");
if ((vmObject.graphics['type'] == 'vnc') || (vmObject.graphics['type'] == 'spice')) {
consoleActions.on("click", kimchi.openVmConsole);
consoleActions.show();
+ secureConsoleActions.on("click", kimchi.openVmSecureConsole);
} else { //we don't recognize the VMs supported graphics, so hide the menu choice
consoleActions.hide();
consoleActions.off("click",kimchi.openVmConsole);
+ secureConsoleActions.hide();
+ secureConsoleActions.off("click", kimchi.openVmSecureConsole);
}
//Setup action event handlers
diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
index c7335c8..6cacc11 100644
--- a/ui/pages/guest.html.tmpl
+++ b/ui/pages/guest.html.tmpl
@@ -56,6 +56,7 @@
<span class="text">$_("Actions")</span><span class="arrow"></span>
<div class="popover actionsheet right-side" style="width: 250px">
<button class="button-big shutoff-disabled" name="vm-console" ><span class="text">$_("Connect")</span></button>
+ <button class="button-big shutoff-disabled" name="vm-secureConsole" ><span class="text">$_("Securely connect")</span></button>
<button class="button-big shutoff-disabled" name="vm-media"><span class="text">$_("Manage Media")</span></button>
<button class="button-big running-disabled" name="vm-edit"><span class="text">$_("Edit")</span></button>
<button class="button-big shutoff-hidden" name="vm-reset"><span class="text">$_("Reset")</span></button>
--
1.8.4.2
10 years, 8 months
[PATCH V2 0/4] vmiface update support
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
V1 -> V2
add test case for running VM
We allow user change the interface from one network to another network
when VM is alive.
But we only support change the vm configure no matter vm is alive or not.
ShaoHe Feng (4):
vmiface update support: update API.md
vmiface update support: update model.
vmiface update support: update mockmodel
vmiface update support: update test case
docs/API.md | 8 ++++++++
src/kimchi/API.json | 17 +++++++++++++++++
src/kimchi/control/vm/ifaces.py | 1 +
src/kimchi/i18n.py | 1 +
src/kimchi/mockmodel.py | 12 ++++++++++++
src/kimchi/model/vmifaces.py | 25 +++++++++++++++++++++++++
tests/test_model.py | 20 ++++++++++++++++++++
tests/test_rest.py | 8 ++++++++
8 files changed, 92 insertions(+)
--
1.9.0
10 years, 8 months
[PATCH V11 0/7] bug fix: get user and group when VM is running
by shaohef@linux.vnet.ibm.com
From: ShaoHe Feng <shaohef(a)linux.vnet.ibm.com>
V10 -> V11
fix typo
V9 -> V10
metadata xml will be changed to hierarchical structure rather than flat.
V8 -> V9
move meta feature test to src/kimchi/model/config.py
use ElementMaker to construct a metanode.
V7 -> V8
add a feature test to probe libvirt support metadata.
add namespace for manully metadata.
V6 -> V7:
After V6 rebase, still find one error code "KCHVM0029E" does not change.
V5 -> V6:
rebase
V4 -> V5:
it is wrong to call dom.isPersistent in V4, fix it.
V3 -> V4:
work around if libvirt do not support metadata API well.
V2 -> V3:
move the virDomain.metadata and virDomain.setMetadata to model/utils.py
add testcase
V1 -> V2:
libvirt also support virDomain.metadata and virDomain.setMetadata two api.
use virDomain.metadata to get the user and group.
use virDomain.setMetadata to set the user and group.
ShaoHe Feng (7):
bug fix: call a method should be followed by "()"
add method to test libvirt metadata api are available
Add two function to set and get domain xml metadata
manually manage the metadata element
bug fix: get user and group when vm is living.
update test case to set/get user and group when VM is running
write the template OS info to vm metadata
src/kimchi/featuretests.py | 33 +++++++++++-
src/kimchi/i18n.py | 1 +
src/kimchi/model/config.py | 2 +
src/kimchi/model/utils.py | 124 +++++++++++++++++++++++++++++++++++++++++++++
src/kimchi/model/vms.py | 105 +++++++++++++++++++++++---------------
tests/test_model.py | 13 +++++
6 files changed, 236 insertions(+), 42 deletions(-)
--
1.9.0
10 years, 8 months
[PATCHv3 0/3] UI: Manage guest disks
by lvroyce@linux.vnet.ibm.com
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
v1>v3,
Fix disk view display,
Fix align problem in select menu,
Fill default value in pool and volume box.
Royce Lv (3):
Fix select menu data append
UI: Support add guest disk
Display all disk types in storage edit view
ui/css/theme-default/guest-storage-add.css | 16 ++++
ui/js/src/kimchi.guest_edit_main.js | 5 +-
ui/js/src/kimchi.guest_storage_add.main.js | 114 +++++++++++++++++++++++++++--
ui/js/widgets/select-menu.js | 4 +-
ui/pages/guest-edit.html.tmpl | 17 ++++-
ui/pages/guest-storage-add.html.tmpl | 62 ++++++++++++++--
6 files changed, 199 insertions(+), 19 deletions(-)
--
1.8.3.2
10 years, 8 months
[PATCH V2] Fix PEP8 in scan.py
by Rodrigo Trujillo
Fixes PEP8 issues in src/kimchi/scan.py and adds it to PEP8_WHITELIST.
Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo(a)linux.vnet.ibm.com>
---
Makefile.am | 1 +
src/kimchi/scan.py | 15 +++++++++------
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 1e4a8be..9785de9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,6 +60,7 @@ PEP8_WHITELIST = \
src/kimchi/repositories.py \
src/kimchi/rollbackcontext.py \
src/kimchi/root.py \
+ src/kimchi/scan.py \
src/kimchi/server.py \
src/kimchi/swupdate.py \
src/kimchi/template.py \
diff --git a/src/kimchi/scan.py b/src/kimchi/scan.py
index b67e3a5..e50dbbc 100644
--- a/src/kimchi/scan.py
+++ b/src/kimchi/scan.py
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
import glob
@@ -32,6 +32,7 @@ from kimchi.utils import kimchi_log
SCAN_IGNORE = ['/tmp/kimchi-scan-*']
+
class Scanner(object):
SCAN_TTL = 300
@@ -56,8 +57,8 @@ class Scanner(object):
shutil.rmtree(d)
self.clean_cb(transient_pool)
except OSError as e:
- kimchi_log.debug(
- "Exception %s occured when cleaning stale pool, ignore" % e.message)
+ msg = "Exception %s occured when cleaning stale pool, ignore"
+ kimchi_log.debug(msg % e.message)
def scan_dir_prepare(self, name):
# clean stale scan storage pools
@@ -71,16 +72,18 @@ class Scanner(object):
duplicates = "%s/%s*" % (params['pool_path'], iso_name)
for f in glob.glob(duplicates):
iso_img = IsoImage(f)
- if (iso_info['distro'], iso_info['version']) == iso_img.probe():
+ if (iso_info['distro'], iso_info['version']) == \
+ iso_img.probe():
return
- iso_path = iso_name + hashlib.md5(iso_info['path']).hexdigest() + '.iso'
+ iso_path = iso_name + hashlib.md5(iso_info['path']).hexdigest() + \
+ '.iso'
link_name = os.path.join(params['pool_path'],
os.path.basename(iso_path))
os.symlink(iso_info['path'], link_name)
ignore_paths = params.get('ignore_list', [])
scan_params = dict(path=params['scan_path'], updater=updater,
- ignore_list=ignore_paths + SCAN_IGNORE)
+ ignore_list=ignore_paths + SCAN_IGNORE)
probe_iso(None, scan_params)
cb('', True)
--
1.9.0
10 years, 8 months
[PATCH] security: Prevent XSS attacks
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
Add the following headers to Kimchi responses:
X-Frame-Options DENY;
X-Content-Type-Options nosniff;
X-XSS-Protection "1; mode=block";
And Content-Security-Policy for error pages.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
src/kimchi/root.py | 11 +++++++++++
src/nginx.conf.in | 4 ++++
2 files changed, 15 insertions(+)
diff --git a/src/kimchi/root.py b/src/kimchi/root.py
index 514d75d..8b1d09b 100644
--- a/src/kimchi/root.py
+++ b/src/kimchi/root.py
@@ -47,18 +47,29 @@ class Root(Resource):
self._cp_config = dict([(key, self.error_development_handler)
for key in self._handled_error])
+ def _set_CSP(self):
+ # set Content-Security-Policy to prevent XSS attacks
+ headers = cherrypy.response.headers
+ headers['Content-Security-Policy'] = "default-src 'self'"
+
def error_production_handler(self, status, message, traceback, version):
+ self._set_CSP()
+
data = {'code': status, 'reason': message}
res = template.render('error.html', data)
+
if (type(res) is unicode and
LooseVersion(cherrypy.__version__) < LooseVersion('3.2.5')):
res = res.encode("utf-8")
return res
def error_development_handler(self, status, message, traceback, version):
+ self._set_CSP()
+
data = {'code': status, 'reason': message,
'call_stack': cherrypy._cperror.format_exc()}
res = template.render('error.html', data)
+
if (type(res) is unicode and
LooseVersion(cherrypy.__version__) < LooseVersion('3.2.5')):
res = res.encode("utf-8")
diff --git a/src/nginx.conf.in b/src/nginx.conf.in
index 967b46b..da6358e 100644
--- a/src/nginx.conf.in
+++ b/src/nginx.conf.in
@@ -47,6 +47,10 @@ http {
ssl_certificate $cert_pem;
ssl_certificate_key $cert_key;
+ add_header X-Frame-Options DENY;
+ add_header X-Content-Type-Options nosniff;
+ add_header X-XSS-Protection "1; mode=block";
+
location / {
proxy_pass http://localhost:$kimchid_port;
proxy_set_header Host $host;
--
1.7.10.4
10 years, 8 months
[PATCH V2] bug fix: Use secure cookies
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
Since this cookie does not contain the "secure" attribute, it might also
be sent to the site during an unencrypted session. Any information such
as cookies, session tokens or user credentials that are sent to the
server as clear text, may be stolen and used later for identity theft or
user impersonation.
Fix it.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
src/kimchi/config.py.in | 1 +
tests/test_config.py.in | 1 +
ui/js/src/kimchi.cookie.js | 1 +
3 files changed, 3 insertions(+)
diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in
index f8a645a..da89e3a 100644
--- a/src/kimchi/config.py.in
+++ b/src/kimchi/config.py.in
@@ -172,6 +172,7 @@ class KimchiConfig(dict):
'tools.nocache.on': True,
'tools.sessions.on': True,
'tools.sessions.name': 'kimchi',
+ 'tools.sessions.secure': True,
'tools.sessions.httponly': True,
'tools.sessions.locking': 'explicit',
'tools.sessions.storage_type': 'ram',
diff --git a/tests/test_config.py.in b/tests/test_config.py.in
index 9654016..cf89fa3 100644
--- a/tests/test_config.py.in
+++ b/tests/test_config.py.in
@@ -97,6 +97,7 @@ class ConfigTests(unittest.TestCase):
'tools.nocache.on': True,
'tools.sessions.on': True,
'tools.sessions.name': 'kimchi',
+ 'tools.sessions.secure': True,
'tools.sessions.httponly': True,
'tools.sessions.locking': 'explicit',
'tools.sessions.storage_type': 'ram',
diff --git a/ui/js/src/kimchi.cookie.js b/ui/js/src/kimchi.cookie.js
index d63fb97..2a69407 100644
--- a/ui/js/src/kimchi.cookie.js
+++ b/ui/js/src/kimchi.cookie.js
@@ -18,6 +18,7 @@
kimchi.cookie = {
set: function(key, value, expireDays) {
value = encodeURIComponent(value);
+ value += '; secure'
if (expireDays) {
var expireDate = new Date();
expireDate.setDate(expireDate.getDate() + expireDays);
--
1.7.10.4
10 years, 8 months
[PATCH] security: Redirect all HTTP requests to HTTPS
by Aline Manera
From: Aline Manera <alinefm(a)br.ibm.com>
Improve kimchi security by redirecting all HTTP requests to HTTPS that
way we make sure all information will be send in a secure way to and
from the server.
Also add Strict-Transport-Security header to avoid SSL stripping
(https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping)
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
src/nginx.conf.in | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/nginx.conf.in b/src/nginx.conf.in
index 967b46b..9218032 100644
--- a/src/nginx.conf.in
+++ b/src/nginx.conf.in
@@ -17,7 +17,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
-
# This is a template file to be used to generate a nginx
# proxy config file at kimchid script.
@@ -30,7 +29,6 @@ events {
worker_connections 1024;
}
-
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
@@ -38,18 +36,26 @@ http {
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
-
- sendfile on;
+ sendfile on;
server {
- listen $proxy_port;
listen $proxy_ssl_port ssl;
+
ssl_certificate $cert_pem;
ssl_certificate_key $cert_key;
+ add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
+
location / {
proxy_pass http://localhost:$kimchid_port;
proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
+
+ server {
+ listen $proxy_port;
+ rewrite ^/(.*)$ https://$host:$proxy_ssl_port/$1 redirect;
+ }
}
--
1.7.10.4
10 years, 8 months