diff --git a/@xen-orchestra/fs/src/_encryptor.js b/@xen-orchestra/fs/src/_encryptor.js index 2125bcb600b..2f841b24b35 100644 --- a/@xen-orchestra/fs/src/_encryptor.js +++ b/@xen-orchestra/fs/src/_encryptor.js @@ -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) { diff --git a/@xen-orchestra/fs/src/index.js b/@xen-orchestra/fs/src/index.js index dd0655ee6ad..5599b23e45c 100644 --- a/@xen-orchestra/fs/src/index.js +++ b/@xen-orchestra/fs/src/index.js @@ -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, diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index d2aa74027c9..cc2850db4b9 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -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 diff --git a/packages/xo-server/src/xo-mixins/remotes.mjs b/packages/xo-server/src/xo-mixins/remotes.mjs index 2c666afdde1..37df84cb9b7 100644 --- a/packages/xo-server/src/xo-mixins/remotes.mjs +++ b/packages/xo-server/src/xo-mixins/remotes.mjs @@ -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 ) diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index dd7f7bbbbbc..01a858d5700 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -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', diff --git a/packages/xo-web/src/xo-app/settings/remotes/index.js b/packages/xo-web/src/xo-app/settings/remotes/index.js index d3bc93383ee..d575c039a3b 100644 --- a/packages/xo-web/src/xo-app/settings/remotes/index.js +++ b/packages/xo-web/src/xo-app/settings/remotes/index.js @@ -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 ? : null + } else { + // remote enabled and not encrypted + if (remote.info.encryption.algorithm === 'none') { + return null + } + const { algorithm, isLegacy, recommendedAlgorithm } = remote.info.encryption + return ( + + + + + + {isLegacy && ( + + + + )} + + ) + } + }, + 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, ]