From 8592de95fa0920f6d19c1fa455139fea647f7c87 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 3 Mar 2023 13:08:17 +0100 Subject: [PATCH] Move PassphraseVO to use String instead of byte[] to support Encrypt annotation (#7302) Co-authored-by: Marcus Sorensen --- .../orchestration/VolumeOrchestrator.java | 6 +-- .../cloudstack/secret/PassphraseVO.java | 39 ++++++++++++------- .../utils/cryptsetup/CryptSetupTest.java | 2 +- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index 4808733bd2e..ad7da2ceace 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -319,8 +319,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati newVol.setFormat(oldVol.getFormat()); if (oldVol.getPassphraseId() != null) { - PassphraseVO passphrase = passphraseDao.persist(new PassphraseVO()); - passphrase.clearPassphrase(); + PassphraseVO passphrase = passphraseDao.persist(new PassphraseVO(true)); newVol.setPassphraseId(passphrase.getId()); } @@ -1801,8 +1800,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } s_logger.debug("Creating passphrase for the volume: " + volume.getName()); long startTime = System.currentTimeMillis(); - PassphraseVO passphrase = passphraseDao.persist(new PassphraseVO()); - passphrase.clearPassphrase(); + PassphraseVO passphrase = passphraseDao.persist(new PassphraseVO(true)); volume.setPassphraseId(passphrase.getId()); long finishTime = System.currentTimeMillis(); s_logger.debug("Creating and persisting passphrase took: " + (finishTime - startTime) + " ms for the volume: " + volume.toString()); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/secret/PassphraseVO.java b/engine/schema/src/main/java/org/apache/cloudstack/secret/PassphraseVO.java index 1c0e5e47ec9..7d70eff3dc1 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/secret/PassphraseVO.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/secret/PassphraseVO.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.secret; import com.cloud.utils.db.Encrypt; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.commons.lang3.StringUtils; import javax.persistence.Column; import javax.persistence.Entity; @@ -27,6 +28,7 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; + import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; @@ -42,32 +44,39 @@ public class PassphraseVO { @Column(name = "passphrase") @Encrypt - private byte[] passphrase; + private String passphrase; public PassphraseVO() { - try { - SecureRandom random = SecureRandom.getInstanceStrong(); - byte[] temporary = new byte[48]; // 48 byte random passphrase buffer - this.passphrase = new byte[64]; // 48 byte random passphrase as base64 for usability - random.nextBytes(temporary); - Base64.getEncoder().encode(temporary, this.passphrase); - Arrays.fill(temporary, (byte) 0); // clear passphrase from buffer - } catch (NoSuchAlgorithmException ex ) { - throw new CloudRuntimeException("Volume encryption requested but system is missing specified algorithm to generate passphrase"); + } + + public PassphraseVO(boolean initialize) { + if (initialize) { + try { + SecureRandom random = SecureRandom.getInstanceStrong(); + byte[] temporary = new byte[48]; // 48 byte random passphrase buffer + random.nextBytes(temporary); + this.passphrase = Base64.getEncoder().encodeToString(temporary); + Arrays.fill(temporary, (byte) 0); // clear passphrase from buffer + } catch (NoSuchAlgorithmException ex ) { + throw new CloudRuntimeException("Volume encryption requested but system is missing specified algorithm to generate passphrase"); + } } } public PassphraseVO(PassphraseVO existing) { - this.passphrase = existing.getPassphrase(); + this.passphrase = existing.getPassphraseString(); } - public void clearPassphrase() { - if (this.passphrase != null) { - Arrays.fill(this.passphrase, (byte) 0); + public byte[] getPassphrase() { + if (StringUtils.isBlank(this.passphrase)) { + return new byte[]{}; } + return this.passphrase.getBytes(); } - public byte[] getPassphrase() { return this.passphrase; } + public String getPassphraseString() { + return this.passphrase; + } public Long getId() { return this.id; } } diff --git a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/cryptsetup/CryptSetupTest.java b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/cryptsetup/CryptSetupTest.java index 007d2c6dc64..c54bbe7354c 100644 --- a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/cryptsetup/CryptSetupTest.java +++ b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/cryptsetup/CryptSetupTest.java @@ -51,7 +51,7 @@ public class CryptSetupTest { file.close(); String filePath = path.toAbsolutePath().toString(); - PassphraseVO passphrase = new PassphraseVO(); + PassphraseVO passphrase = new PassphraseVO(true); cryptSetup.luksFormat(passphrase.getPassphrase(), CryptSetup.LuksType.LUKS, filePath);