diff --git a/www/manager6/storage/PBSEdit.js b/www/manager6/storage/PBSEdit.js index c471c65a..ce72fd1a 100644 --- a/www/manager6/storage/PBSEdit.js +++ b/www/manager6/storage/PBSEdit.js @@ -1,3 +1,4 @@ +/*global QRCode*/ Ext.define('Proxmox.form.PBSEncryptionCheckbox', { extend: 'Ext.form.field.Checkbox', xtype: 'pbsEncryptionCheckbox', @@ -60,11 +61,203 @@ Ext.define('Proxmox.form.PBSEncryptionCheckbox', { vm.set('isCreate', me.isCreate); }, }); + +Ext.define('PVE.Storage.PBSKeyShow', { + extend: 'Ext.window.Window', + alias: ['widget.pveKeyShow'], + mixins: ['Proxmox.Mixin.CBind'], + + width: 600, + modal: true, + resizable: false, + title: gettext('Important: Save your Encryption Key'), + + // avoid that esc closes this by mistake, force user to more manual action + onEsc: Ext.emptyFn, + closable: false, + + items: [ + { + xtype: 'form', + layout: { + type: 'vbox', + align: 'stretch', + }, + bodyPadding: 10, + border: false, + defaults: { + anchor: '100%', + border: false, + padding: '10 0 0 0', + }, + items: [ + { + xtype: 'textfield', + fieldLabel: gettext('Key'), + labelWidth: 30, + inputId: 'encryption-key-value', + cbind: { + value: '{key}', + }, + editable: false, + }, + { + xtype: 'component', + html: gettext('Keep your master key safe, but easily accessible for disaster recovery.') + + '
' + gettext('We recommend the following safe-keeping strategy:'), + }, + { + xtyp: 'container', + layout: 'hbox', + items: [ + { + xtype: 'component', + html: '1. ' + gettext('Save the key in your password manager.'), + flex: 1, + }, + { + xtype: 'button', + text: gettext('Copy Key'), + iconCls: 'fa fa-clipboard x-btn-icon-el-default-toolbar-small', + cls: 'x-btn-default-toolbar-small proxmox-inline-button', + width: 110, + handler: function(b) { + document.getElementById('encryption-key-value').select(); + document.execCommand("copy"); + }, + }, + ], + }, + { + xtype: 'container', + layout: 'hbox', + items: [ + { + xtype: 'component', + html: '2. ' + gettext('Download the key to a USB (pen) drive, placed in secure vault.'), + flex: 1, + }, + { + xtype: 'button', + text: gettext('Download'), + iconCls: 'fa fa-download x-btn-icon-el-default-toolbar-small', + cls: 'x-btn-default-toolbar-small proxmox-inline-button', + width: 110, + handler: function(b) { + let win = this.up('window'); + + let pveID = PVE.ClusterName || window.location.hostname; + let name = `pve-${pveID}-storage-${win.sid}.enc`; + + let hiddenElement = document.createElement('a'); + hiddenElement.href = 'data:attachment/text,' + encodeURI(win.key); + hiddenElement.target = '_blank'; + hiddenElement.download = name; + hiddenElement.click(); + }, + }, + ], + }, + { + xtype: 'container', + layout: 'hbox', + items: [ + { + xtype: 'component', + html: '3. ' + gettext('Print as paperkey, laminated and placed in secure vault.'), + flex: 1, + }, + { + xtype: 'button', + text: gettext('Print Key'), + iconCls: 'fa fa-print x-btn-icon-el-default-toolbar-small', + cls: 'x-btn-default-toolbar-small proxmox-inline-button', + width: 110, + handler: function(b) { + let win = this.up('window'); + win.paperkey(win.key); + }, + }, + ], + }, + ], + }, + { + xtype: 'component', + border: false, + padding: '10 10 10 10', + userCls: 'pmx-hint', + html: gettext('Please save the encryption key - loosing it will render any backup created with it unuseable'), + }, + ], + buttons: [ + { + text: gettext('Close'), + handler: function(b) { + let win = this.up('window'); + win.close(); + }, + }, + ], + paperkey: function(key) { + let me = this; + + const qrwidth = 500; + let qrdiv = document.createElement('div'); + let qrcode = new QRCode(qrdiv, { + width: qrwidth, + height: qrwidth, + correctLevel: QRCode.CorrectLevel.H, + }); + qrcode.makeCode(key); + + let printFrame = document.createElement("iframe"); + Object.assign(printFrame.style, { + position: "fixed", + right: "0", + bottom: "0", + width: "0", + height: "0", + border: "0", + }); + const prettifiedKey = JSON.stringify(JSON.parse(key), null, 2); + const keyQrBase64 = qrdiv.children[0].toDataURL("image/png"); + const html = ` +

Encryption Key - Storage '${me.sid}'

+

+-----BEGIN PROXMOX BACKUP KEY----- +${prettifiedKey} +-----END PROXMOX BACKUP KEY-----

+
+ `; + + printFrame.src = "data:text/html;base64," + btoa(html); + document.body.appendChild(printFrame); + }, +}); + Ext.define('PVE.storage.PBSInputPanel', { extend: 'PVE.panel.StorageBase', //onlineHelp: 'storage_pbs', + apiCallDone: function(success, response, options) { + let res = response.result.data; + if (!(res && res.config && res.config['encryption-key'])) { + return; + } + let key = res.config['encryption-key']; + Ext.create('PVE.Storage.PBSKeyShow', { + autoShow: true, + sid: res.storage, + key: key, + }); + }, + initComponent: function() { var me = this;