Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions conf/errorCodes/ZMigratePlugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<error>
<prefix>ZMigrate</prefix>

<code>
<id>1000</id>
<description>ZCE-X generic error</description>
</code>

<code>
<id>1001</id>
<description>Failed to connect ZCE-X server</description>
</code>

<code>
<id>1002</id>
<description>Authorization fails in ZCE-X server</description>
</code>

<code>
<id>1003</id>
<description>ZCE-X API operation fail</description>
</code>
</error>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.zstack.header.storage.backup;

import org.zstack.header.message.NeedReplyMessage;

public class CopyFileFromBackupStorageHostMsg extends NeedReplyMessage implements BackupStorageMessage {
private String backupStorageUuid;
private String backupStorageHostUuid;
private String dstHostname;
private String dstSshPassword;
private String dstSshUsername;
private int dstSshPort;
private String dstFilePath;
private String targetFilePath;

@Override
public String getBackupStorageUuid() {
return backupStorageUuid;
}

public void setBackupStorageUuid(String backupStorageUuid) {
this.backupStorageUuid = backupStorageUuid;
}

public String getBackupStorageHostUuid() {
return backupStorageHostUuid;
}

public void setBackupStorageHostUuid(String backupStorageHostUuid) {
this.backupStorageHostUuid = backupStorageHostUuid;
}

public String getDstHostname() {
return dstHostname;
}

public void setDstHostname(String dstHostname) {
this.dstHostname = dstHostname;
}

public String getDstSshPassword() {
return dstSshPassword;
}

public void setDstSshPassword(String dstSshPassword) {
this.dstSshPassword = dstSshPassword;
Comment on lines +9 to +45
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the full CopyFileFromBackupStorageHostMsg.java file
cat header/src/main/java/org/zstack/header/image/CopyFileFromBackupStorageHostMsg.java

Repository: MatheMatrix/zstack

Length of output: 2121


🏁 Script executed:

# Search for password handling patterns and annotations in the codebase
rg -n '@Convert|@NoLogging|@Sensitive|@Secret|@Credential|PasswordConverter' --type=java -A 2 -B 2 | head -100

Repository: MatheMatrix/zstack

Length of output: 9767


🏁 Script executed:

# Look for message serialization/logging mechanisms
rg -n 'getMessage|toString|serialize|toJson|marshal' --type=java header/src/main/java/org/zstack/header/ | grep -i message | head -50

Repository: MatheMatrix/zstack

Length of output: 6807


🏁 Script executed:

# Search for similar SSH credential fields in the codebase
rg -n 'SshPassword|sshPassword|dstSshPassword' --type=java -B 2 -A 2 | head -80

Repository: MatheMatrix/zstack

Length of output: 7541


🏁 Script executed:

# Check if there's a base message class that handles sensitive field masking
rg -n 'class.*Message.*\{' --type=java header/src/main/java/org/zstack/header/ | head -20

Repository: MatheMatrix/zstack

Length of output: 3294


dstSshPassword 字段上添加 @NoLogging 注解以防止敏感信息泄露。

dstSshPassword 字段缺少 @NoLogging 注解。该字段作为明文 String 存储在消息对象中,当消息被序列化用于日志或审计时,敏感的 SSH 密码凭证可能被意外输出。ZStack 整个代码库中对敏感字段的标准做法是使用 @NoLogging 注解(如 APIAddSftpBackupStorageMsgKVMAgentCommands 等)。请在此字段添加该注解以符合安全标准:

`@NoLogging`
private String dstSshPassword;
🤖 Prompt for AI Agents
In
`@header/src/main/java/org/zstack/header/image/CopyFileFromBackupStorageHostMsg.java`
around lines 10 - 46, Add the `@NoLogging` annotation to the sensitive field
dstSshPassword in class CopyFileFromBackupStorageHostMsg by placing `@NoLogging`
immediately above the private String dstSshPassword declaration; also add the
corresponding import for the NoLogging annotation (e.g.,
org.zstack.header.message.NoLogging) if missing and run a quick compile to
ensure no unused-import or annotation issues.

}

public String getDstSshUsername() {
return dstSshUsername;
}

public void setDstSshUsername(String dstSshUsername) {
this.dstSshUsername = dstSshUsername;
}

public int getDstSshPort() {
return dstSshPort;
}

public void setDstSshPort(int dstSshPort) {
this.dstSshPort = dstSshPort;
}

public String getDstFilePath() {
return dstFilePath;
}

public void setDstFilePath(String dstFilePath) {
this.dstFilePath = dstFilePath;
}

public String getTargetFilePath() {
return targetFilePath;
}

public void setTargetFilePath(String targetFilePath) {
this.targetFilePath = targetFilePath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.zstack.header.storage.backup;

import org.zstack.header.message.MessageReply;

public class CopyFileFromBackupStorageHostReply extends MessageReply {
private String upgradeScriptPath;

public String getUpgradeScriptPath() {
return upgradeScriptPath;
}

public void setUpgradeScriptPath(String upgradeScriptPath) {
this.upgradeScriptPath = upgradeScriptPath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.zstack.header.storage.backup;

import org.zstack.header.message.NeedReplyMessage;

import java.util.List;

public class DeleteFilesOnBackupStorageHostMsg extends NeedReplyMessage implements BackupStorageMessage {
private String backupStorageUuid;
private String backupStorageHostUuid;
private List<String> filesPath;

@Override
public String getBackupStorageUuid() {
return backupStorageUuid;
}

public void setBackupStorageUuid(String backupStorageUuid) {
this.backupStorageUuid = backupStorageUuid;
}

public String getBackupStorageHostUuid() {
return backupStorageHostUuid;
}

public void setBackupStorageHostUuid(String backupStorageHostUuid) {
this.backupStorageHostUuid = backupStorageHostUuid;
}

public List<String> getFilesPath() {
return filesPath;
}

public void setFilesPath(List<String> filesPath) {
this.filesPath = filesPath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.zstack.header.storage.backup;

import org.zstack.header.log.NoLogging;
import org.zstack.header.message.MessageReply;

import java.util.Map;

public class DeleteFilesOnBackupStorageHostReply extends MessageReply {
private String md5sum;
private long size;
@NoLogging(type = NoLogging.Type.Uri)
private String directUploadUrl;
private String unzipInstallPath;
private Map<String, Long> filesSize;
Comment on lines +8 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

字段与删除操作语义不匹配,疑似复制粘贴错误。

当前 DeleteFilesOnBackupStorageHostReply 的字段(md5sumsizedirectUploadUrlunzipInstallPathfilesSize)与 UploadFileToBackupStorageHostReply 几乎完全相同。这些字段对于删除操作来说不太合理:

  • md5sumdirectUploadUrlunzipInstallPath 是上传/下载相关的属性
  • 删除操作通常只需返回操作结果状态(已由 MessageReply 提供)

请确认这是否为预期设计,或者是否应该移除这些与删除操作无关的字段。

🤖 Prompt for AI Agents
In
`@header/src/main/java/org/zstack/header/storage/backup/DeleteFilesOnBackupStorageHostReply.java`
around lines 8 - 14, The reply class DeleteFilesOnBackupStorageHostReply
contains upload-related fields (md5sum, size, directUploadUrl, unzipInstallPath,
filesSize) that don't match a delete operation; remove these fields from the
DeleteFilesOnBackupStorageHostReply class so it only relies on MessageReply for
status/error info (if you need any delete-specific metadata, add a clearly named
field and javadoc). Update/remove any getters/setters or usages referring to
md5sum, size, directUploadUrl, unzipInstallPath, or filesSize (search for those
symbols) to avoid compilation errors.


public String getMd5sum() {
return md5sum;
}

public void setMd5sum(String md5sum) {
this.md5sum = md5sum;
}

public long getSize() {
return size;
}

public void setSize(long size) {
this.size = size;
}

public String getDirectUploadUrl() {
return directUploadUrl;
}

public void setDirectUploadUrl(String directUploadUrl) {
this.directUploadUrl = directUploadUrl;
}

public String getUnzipInstallPath() {
return unzipInstallPath;
}

public void setUnzipInstallPath(String unzipInstallPath) {
this.unzipInstallPath = unzipInstallPath;
}

public Map<String, Long> getFilesSize() {
return filesSize;
}

public void setFilesSize(Map<String, Long> filesSize) {
this.filesSize = filesSize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.zstack.header.storage.backup;

import org.zstack.header.message.NeedReplyMessage;

public class GetFileDownloadProgressMsg extends NeedReplyMessage implements BackupStorageMessage {
private String backupStorageUuid;
private String backupStorageHostUuid;
private String taskUuid;
private String hostname;

@Override
public String getBackupStorageUuid() {
return backupStorageUuid;
}

public void setBackupStorageUuid(String backupStorageUuid) {
this.backupStorageUuid = backupStorageUuid;
}

public String getBackupStorageHostUuid() {
return backupStorageHostUuid;
}

public void setBackupStorageHostUuid(String backupStorageHostUuid) {
this.backupStorageHostUuid = backupStorageHostUuid;
}

public String getTaskUuid() {
return taskUuid;
}

public void setTaskUuid(String taskUuid) {
this.taskUuid = taskUuid;
}

public String getHostname() {
return hostname;
}

public void setHostname(String hostname) {
this.hostname = hostname;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.zstack.header.storage.backup;

import org.zstack.header.message.MessageReply;

import java.util.Map;

public class GetFileDownloadProgressReply extends MessageReply {
private boolean completed;
private int progress;

private long size;
private long actualSize;
private long downloadSize;
private String installPath;
private long lastOpTime;
private boolean supportSuspend;
private String md5sum;
private String format;

private String unzipInstallPath;
private Map<String, Long> unzipFiles;

public boolean isCompleted() {
return completed;
}

public void setCompleted(boolean completed) {
this.completed = completed;
}

public int getProgress() {
return progress;
}

public void setProgress(int progress) {
this.progress = progress;
}

public long getSize() {
return size;
}

public void setSize(long size) {
this.size = size;
}

public long getActualSize() {
return actualSize;
}

public void setActualSize(long actualSize) {
this.actualSize = actualSize;
}

public boolean isDownloadComplete() {
return actualSize > 0 && actualSize == downloadSize;
}

public String getInstallPath() {
return installPath;
}

public void setInstallPath(String installPath) {
this.installPath = installPath;
}

public String getFormat() {
return format;
}

public void setFormat(String format) {
this.format = format;
}

public long getLastOpTime() {
return lastOpTime;
}

public void setLastOpTime(long lastOpTime) {
this.lastOpTime = lastOpTime;
}

public long getDownloadSize() {
return downloadSize;
}

public void setDownloadSize(long downloadSize) {
this.downloadSize = downloadSize;
}

public boolean isSupportSuspend() {
return supportSuspend;
}

public void setSupportSuspend(boolean supportSuspend) {
this.supportSuspend = supportSuspend;
}

public String getMd5sum() {
return md5sum;
}

public void setMd5sum(String md5sum) {
this.md5sum = md5sum;
}

public String getUnzipInstallPath() {
return unzipInstallPath;
}

public void setUnzipInstallPath(String unzipInstallPath) {
this.unzipInstallPath = unzipInstallPath;
}

public Map<String, Long> getUnzipFiles() {
return unzipFiles;
}

public void setUnzipFiles(Map<String, Long> unzipFiles) {
this.unzipFiles = unzipFiles;
}
}
Loading