]> git.proxmox.com Git - pve-manager.git/commitdiff
lxc: wizard: ssh key
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 10 Aug 2016 10:13:19 +0000 (12:13 +0200)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Fri, 19 Aug 2016 11:54:38 +0000 (13:54 +0200)
www/manager6/Parser.js
www/manager6/lxc/CreateWizard.js

index c049d062d60f6cec297f49e04a53b4eb5e290609..c796d35b525fa1dac2669e8afe20b6bb8e1caf5a 100644 (file)
@@ -493,5 +493,35 @@ Ext.define('PVE.Parser', { statics: {
        }
 
        return cpustr + optstr;
+    },
+
+    parseSSHKey: function(key) {
+       //                |--- options can have quotes--|     type    key        comment
+       var keyre = /^(?:((?:[^\s"]|\"(?:\\.|[^"\\])*")+)\s+)?(\S+)\s+(\S+)(?:\s+(.*))?$/;
+       var typere = /^(?:ssh-(?:dss|rsa|ed25519)|ecdsa-sha2-nistp\d+)$/;
+
+       var m = key.match(keyre);
+       if (!m) {
+           return null;
+       }
+       if (m.length < 3 || !m[2]) { // [2] is always either type or key
+           return null;
+       }
+       if (m[1] && m[1].match(typere)) {
+           return {
+               type: m[1],
+               key: m[2],
+               comment: m[3]
+           };
+       }
+       if (m[2].match(typere)) {
+           return {
+               options: m[1],
+               type: m[2],
+               key: m[3],
+               comment: m[4]
+           };
+       }
+       return null;
     }
 }});
index b0df998968435937c75e604ec90730d1d25b45bc..a6cb59d9f776498cb2e2deb30873c415dfdbe20e 100644 (file)
@@ -2,6 +2,23 @@
 Ext.define('PVE.lxc.CreateWizard', {
     extend: 'PVE.window.Wizard',
 
+    loadSSHKeyFromFile: function(file) {
+       var me = this;
+       // ssh-keygen produces 740 bytes for an average 4096 bit rsa key, with
+       // a user@host comment, 1420 for 8192 bits; current max is 16kbit
+       // assume: 740*8 for max. 32kbit (5920 byte file)
+       // round upwards to nearest nice number => 8192 bytes, leaves lots of comment space
+       if (file.size > 8192) {
+           Ext.Msg.alert(gettext('Error'), gettext("Invalid file size: ") + file.size);
+           return;
+       }
+       var reader = new FileReader();
+       reader.onload = function(evt) {
+           me.sshkeyfield.setValue(evt.target.result);
+       };
+       reader.readAsText(file);
+    },
+
     initComponent: function() {
        var me = this;
 
@@ -50,6 +67,106 @@ Ext.define('PVE.lxc.CreateWizard', {
            create: true
        });
 
+       var passwordfield = Ext.createWidget('textfield', {
+           inputType: 'password',
+           name: 'password',
+           value: '',
+           fieldLabel: gettext('Password'),
+           allowBlank: false,
+           minLength: 5,
+           change: function(f, value) {
+               if (!me.rendered) {
+                   return;
+               }
+               me.down('field[name=confirmpw]').validate();
+           }
+       });
+
+       me.sshkeyfield = Ext.createWidget('textfield', {
+           xtype: 'textfield',
+           name: 'ssh-public-keys',
+           value: '',
+           fieldLabel: gettext('SSH public key'),
+           allowBlank: true,
+           validator: function(value) {
+               if (value.length) {
+                   var key = PVE.Parser.parseSSHKey(value);
+                   if (!key) {
+                       return "Failed to recognize ssh key";
+                   }
+                   me.down('field[name=password]').allowBlank = true;
+               } else {
+                   me.down('field[name=password]').allowBlank = false;
+               }
+               me.down('field[name=password]').validate();
+               return true;
+           },
+           afterRender: function() {
+               if (!window.FileReader) {
+                   // No FileReader support in this browser
+                   return;
+               }
+               var cancel = function(ev) {
+                   ev = ev.event;
+                   if (ev.preventDefault) {
+                       ev.preventDefault();
+                   }
+               };
+               me.sshkeyfield.inputEl.on('dragover', cancel);
+               me.sshkeyfield.inputEl.on('dragenter', cancel);
+               me.sshkeyfield.inputEl.on('drop', function(ev) {
+                   ev = ev.event;
+                   if (ev.preventDefault) {
+                       ev.preventDefault();
+                   }
+                   var files = ev.dataTransfer.files;
+                   me.loadSSHKeyFromFile(files[0]);
+               });
+           },
+       });
+
+       var column2 = [
+           {
+               xtype: 'pvePoolSelector',
+               fieldLabel: gettext('Resource Pool'),
+               name: 'pool',
+               value: '',
+               allowBlank: true
+           },
+           passwordfield,
+           {
+               xtype: 'textfield',
+               inputType: 'password',
+               name: 'confirmpw',
+               value: '',
+               fieldLabel: gettext('Confirm password'),
+               allowBlank: true,
+               validator: function(value) {
+                   var pw = me.down('field[name=password]').getValue();
+                   if (pw !== value) {
+                       return "Passwords does not match!";
+                   }
+                   return true;
+               }
+           },
+           me.sshkeyfield
+       ];
+
+       if (window.FileReader) {
+           column2.push({
+               xtype: 'filebutton',
+               name: 'file',
+               text: gettext('Load SSH Key File'),
+               listeners: {
+                   change: function(btn, e, value) {
+                       e = e.event;
+                       me.loadSSHKeyFromFile(e.target.files[0]);
+                       btn.reset();
+                   }
+               }
+           });
+       }
+
        Ext.applyIf(me, {
            subject: gettext('LXC Container'),
            items: [
@@ -90,45 +207,7 @@ Ext.define('PVE.lxc.CreateWizard', {
                            allowBlank: true
                        }
                    ],
-                   column2: [
-                       {
-                           xtype: 'pvePoolSelector',
-                           fieldLabel: gettext('Resource Pool'),
-                           name: 'pool',
-                           value: '',
-                           allowBlank: true
-                       },
-                       {
-                           xtype: 'textfield',
-                           inputType: 'password',
-                           name: 'password',
-                           value: '',
-                           fieldLabel: gettext('Password'),
-                           allowBlank: false,
-                           minLength: 5,
-                           change: function(f, value) {
-                               if (!me.rendered) {
-                                   return;
-                               }
-                               me.down('field[name=confirmpw]').validate();
-                           }
-                       },
-                       {
-                           xtype: 'textfield',
-                           inputType: 'password',
-                           name: 'confirmpw',
-                           value: '',
-                           fieldLabel: gettext('Confirm password'),
-                           allowBlank: false,
-                           validator: function(value) {
-                               var pw = me.down('field[name=password]').getValue();
-                               if (pw !== value) {
-                                   return "Passwords does not match!";
-                               }
-                               return true;
-                           }
-                       }
-                   ],
+                   column2: column2,
                    onGetValues: function(values) {
                        delete values.confirmpw;
                        if (!values.pool) {
@@ -204,6 +283,12 @@ Ext.define('PVE.lxc.CreateWizard', {
                        delete kv.nodename;
                        delete kv.tmplstorage;
 
+                       if (!kv['ssh-public-keys'].length) {
+                           delete kv['ssh-public-keys'];
+                       } else if (!kv['password'].length) {
+                           delete kv['password'];
+                       }
+
                        PVE.Utils.API2Request({
                            url: '/nodes/' + nodename + '/lxc',
                            waitMsgTarget: me,