feat(xo-web/remote): show encryption in remote UI (#6465)

* if remote is disabled we don't know the used algorithm : only show the lock if there is an encryption key
* if remote is enabled : 
  *  if algorithm is undefined or none : show nothing, remote is not encrypted
  * if algorithm is defined to DEFAULT_ENCRYPTION_ALGORITHM : show the lock with the name of the algorithm as a tooltip
  * else show the lock and a warning advising to create a new remote with an up to date algorithm
This commit is contained in:
Florent BEAUCHAMP 2022-10-24 16:15:26 +02:00 committed by GitHub
parent 2d4317b681
commit b60f5d593b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 3 deletions

View File

@ -3,6 +3,11 @@ const { readChunk } = require('@vates/read-chunk')
const crypto = require('crypto')
export const DEFAULT_ENCRYPTION_ALGORITHM = 'aes-256-gcm'
export const UNENCRYPTED_ALGORITHM = 'none'
export function isLegacyEncryptionAlgorithm(algorithm) {
return algorithm !== UNENCRYPTED_ALGORITHM && algorithm !== DEFAULT_ENCRYPTION_ALGORITHM
}
function getEncryptor(algorithm = DEFAULT_ENCRYPTION_ALGORITHM, key) {
if (key === undefined) {

View File

@ -5,6 +5,7 @@ import RemoteHandlerLocal from './local'
import RemoteHandlerNfs from './nfs'
import RemoteHandlerS3 from './s3'
import RemoteHandlerSmb from './smb'
export { DEFAULT_ENCRYPTION_ALGORITHM, UNENCRYPTED_ALGORITHM, isLegacyEncryptionAlgorithm } from './_encryptor'
const HANDLERS = {
file: RemoteHandlerLocal,

View File

@ -8,6 +8,7 @@
> Users must be able to say: “Nice enhancement, I'm eager to test it”
- [Backup/Encryption] Use `aes-256-gcm` instead of `aes-256-ccm` to mitigate [padding oracle attacks](https://en.wikipedia.org/wiki/Padding_oracle_attack) (PR [#6447](https://github.com/vatesfr/xen-orchestra/pull/6447))
- [Settings/Remote] Display `lock` icon for encrypted remote and a warning if the remote uses a legacy encryption algorithm (PR [#6465](https://github.com/vatesfr/xen-orchestra/pull/6465))
### Bug fixes
@ -39,7 +40,8 @@
- @xen-orchestra/log minor
- @xen-orchestra/mixins patch
- xo-remote-parser patch
- xo-server minor
- xo-server-transport-nagios patch
- xo-web patch
- xo-web minor
<!--packages-end-->

View File

@ -1,6 +1,11 @@
import asyncMapSettled from '@xen-orchestra/async-map/legacy.js'
import { format, parse } from 'xo-remote-parser'
import { getHandler } from '@xen-orchestra/fs'
import {
DEFAULT_ENCRYPTION_ALGORITHM,
getHandler,
isLegacyEncryptionAlgorithm,
UNENCRYPTED_ALGORITHM,
} from '@xen-orchestra/fs'
import { ignoreErrors, timeout } from 'promise-toolbox'
import { noSuchObject } from 'xo-common/api-errors.js'
import { synchronized } from 'decorator-synchronized'
@ -124,6 +129,17 @@ export default class {
return
}
let encryption
if (this._handlers[remote.id] !== undefined) {
const algorithm = this._handlers[remote.id]._encryptor?.algorithm ?? UNENCRYPTED_ALGORITHM
encryption = {
algorithm,
isLegacy: isLegacyEncryptionAlgorithm(algorithm),
recommendedAlgorithm: DEFAULT_ENCRYPTION_ALGORITHM,
}
}
const promise =
remote.proxy !== undefined
? this._app.callProxyMethod(remote.proxy, 'remote.getInfo', {
@ -134,7 +150,10 @@ export default class {
try {
await timeout.call(
promise.then(info => {
remotesInfo[remote.id] = info
remotesInfo[remote.id] = {
...info,
encryption,
}
}),
5e3
)

View File

@ -611,6 +611,10 @@ const messages = {
remoteEncryptionKey: 'Encrypt all new data sent to this remote',
remoteEncryptionKeyStorageLocation:
"You won't be able to get your data back if you lose the encryption key. The encryption key is saved in the XO config backup, they should be secured correctly. Be careful, if you saved it on an encrypted remote, then you won't be able to access it without the remote encryption key.",
encryption: 'Encryption',
remoteEncryptionLegacy:
'A legacy encryption algorithm is used ({algorithm}), please create a new remote with the recommended algorithm {recommendedAlgorithm}',
// ------ New Storage -----
newSr: 'New SR',

View File

@ -124,6 +124,36 @@ const COLUMN_PROXY = {
name: _('proxy'),
}
const COLUMN_ENCRYPTION = {
itemRenderer: remote => {
// remote.info?.encryption undefined means that remote is not enabled and synced
// we don't have the agorithm used at this step
if (remote.info?.encryption === undefined) {
return remote.encryptionKey !== undefined ? <Icon size='lg' icon='lock' /> : null
} else {
// remote enabled and not encrypted
if (remote.info.encryption.algorithm === 'none') {
return null
}
const { algorithm, isLegacy, recommendedAlgorithm } = remote.info.encryption
return (
<span>
<Tooltip content={algorithm}>
<Icon className='mr-1' icon='lock' size='lg' />
</Tooltip>
{isLegacy && (
<Tooltip content={_('remoteEncryptionLegacy', { algorithm, recommendedAlgorithm })}>
<Icon icon='error' size='lg' />
</Tooltip>
)}
</span>
)
}
},
name: _('encryption'),
}
const fixRemoteUrl = remote => editRemote(remote, { url: format(remote) })
const COLUMNS_LOCAL_REMOTE = [
COLUMN_NAME,
@ -141,6 +171,7 @@ const COLUMNS_LOCAL_REMOTE = [
},
COLUMN_STATE,
COLUMN_DISK,
COLUMN_ENCRYPTION,
COLUMN_SPEED,
COLUMN_PROXY,
]
@ -198,6 +229,7 @@ const COLUMNS_NFS_REMOTE = [
},
COLUMN_STATE,
COLUMN_DISK,
COLUMN_ENCRYPTION,
COLUMN_SPEED,
COLUMN_PROXY,
]
@ -245,6 +277,7 @@ const COLUMNS_SMB_REMOTE = [
),
name: _('remoteAuth'),
},
COLUMN_ENCRYPTION,
COLUMN_SPEED,
COLUMN_PROXY,
]
@ -300,6 +333,7 @@ const COLUMNS_S3_REMOTE = [
),
name: 'Key',
},
COLUMN_ENCRYPTION,
COLUMN_SPEED,
COLUMN_PROXY,
]