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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.zstack.compute.vm.devices;

import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.keyprovider.EncryptedResourceKeyManager;
import org.zstack.header.core.Completion;
import org.zstack.header.core.ReturnValueCompletion;
Expand All @@ -19,6 +20,13 @@ public void getOrCreateKey(GetOrCreateResourceKeyContext ctx,
completion.fail(operr("crypto module is not installed, cannot manage resource encryption keys"));
}

@Override
public ResourceKeyResult getKey(GetOrCreateResourceKeyContext ctx) {
logger.warn(String.format("crypto module not installed, cannot get resource key for %s[uuid:%s]",
ctx.getResourceType(), ctx.getResourceUuid()));
throw new OperationFailureException(operr("crypto module is not installed, cannot manage resource encryption keys"));
}

@Override
public void rollbackCreatedKey(ResourceKeyResult result, Completion completion) {
completion.success();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,34 @@ public interface EncryptedResourceKeyManager {
void getOrCreateKey(GetOrCreateResourceKeyContext ctx,
ReturnValueCompletion<ResourceKeyResult> completion);

/**
* Load the existing resource encryption key material only.
* <p>
* Requires an {@code EncryptedResourceKeyRef} row and a usable secret reference already stored
* for the resource. Does <strong>not</strong> insert a ref row and does <strong>not</strong> call
* key-tool/KMS <em>create</em> APIs.
* <p>
* The implementation may still call key-tool/KMS <em>get/unwrap</em> for the <strong>existing</strong>
* secret ref in order to return the plaintext DEK (for example defining the secret on the destination
* host during hot migration). That RPC is read-side materialization, not secret creation.
* <p>
* On success, the implementation may update {@code EncryptedResourceKeyRef} provider columns to match
* the resolved key provider when they have drifted (same behavior as the existing-key branch of
* {@link #getOrCreateKey}).
*
* @param ctx same fields as {@link #getOrCreateKey}; identifies resource and provider
* @return {@link ResourceKeyResult} with {@code createdNewKey == false} on success
* @throws org.zstack.header.errorcode.OperationFailureException when the key cannot be loaded
*/
ResourceKeyResult getKey(GetOrCreateResourceKeyContext ctx);

/**
* Roll back a newly created resource key during upper-layer workflow rollback.
* <p>
* If the key record already existed before creation, implementation should restore it
* to its previous empty-placeholder state instead of deleting the relationship.
* When {@link ResourceKeyResult#isCreatedNewKey()} is true, the implementation deletes the
* key-tool secret if one was materialized, then removes the {@code EncryptedResourceKeyRef} row
* for the resource (same storage effect as detaching the key provider from the resource).
* When {@code createdNewKey} is false (existing secret was reused), this is a no-op.
*/
void rollbackCreatedKey(ResourceKeyResult result, Completion completion);

Expand Down Expand Up @@ -91,7 +114,6 @@ class ResourceKeyResult {
private String dekBase64;
private String secretRef;
private boolean createdNewKey;
private boolean refExistedBeforeCreate;

public String getResourceUuid() {
return resourceUuid;
Expand Down Expand Up @@ -156,13 +178,5 @@ public boolean isCreatedNewKey() {
public void setCreatedNewKey(boolean createdNewKey) {
this.createdNewKey = createdNewKey;
}

public boolean isRefExistedBeforeCreate() {
return refExistedBeforeCreate;
}

public void setRefExistedBeforeCreate(boolean refExistedBeforeCreate) {
this.refExistedBeforeCreate = refExistedBeforeCreate;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class SecretHostDefineMsg extends NeedReplyMessage implements HostMessage
private String vmUuid;
private String purpose;
private Integer keyVersion;
private String usageInstance;
private String secretUuid;
private String description;

@Override
Expand Down Expand Up @@ -59,6 +61,22 @@ public void setKeyVersion(Integer keyVersion) {
this.keyVersion = keyVersion;
}

public String getUsageInstance() {
return usageInstance;
}

public void setUsageInstance(String usageInstance) {
this.usageInstance = usageInstance;
}

public String getSecretUuid() {
return secretUuid;
}

public void setSecretUuid(String secretUuid) {
this.secretUuid = secretUuid;
}

public String getDescription() {
return description;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class SecretHostDeleteMsg extends NeedReplyMessage implements HostMessage
private String vmUuid;
private String purpose;
private Integer keyVersion;
private String usageInstance;

@Override
public String getHostUuid() {
Expand Down Expand Up @@ -41,4 +42,12 @@ public Integer getKeyVersion() {
public void setKeyVersion(Integer keyVersion) {
this.keyVersion = keyVersion;
}

public String getUsageInstance() {
return usageInstance;
}

public void setUsageInstance(String usageInstance) {
this.usageInstance = usageInstance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class SecretHostGetMsg extends NeedReplyMessage implements HostMessage {
private String vmUuid;
private String purpose;
private Integer keyVersion;
private String usageInstance;

@Override
public String getHostUuid() {
Expand Down Expand Up @@ -44,4 +45,12 @@ public Integer getKeyVersion() {
public void setKeyVersion(Integer keyVersion) {
this.keyVersion = keyVersion;
}

public String getUsageInstance() {
return usageInstance;
}

public void setUsageInstance(String usageInstance) {
this.usageInstance = usageInstance;
}
}
27 changes: 18 additions & 9 deletions plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,9 @@ public static class SecretHostDefineCmd extends AgentCommand {
private String vmUuid;
private String purpose;
private Integer keyVersion;
private String description;
private String usageInstance;
private String secretUuid;
private String description;

public String getEncryptedDek() {
return encryptedDek;
Expand Down Expand Up @@ -446,21 +447,29 @@ public void setKeyVersion(Integer keyVersion) {
this.keyVersion = keyVersion;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getUsageInstance() {
return usageInstance;
}

public void setUsageInstance(String usageInstance) {
this.usageInstance = usageInstance;
}

public String getSecretUuid() {
return secretUuid;
}

public void setSecretUuid(String secretUuid) {
this.secretUuid = secretUuid;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}

public static class SecretHostDefineResponse extends AgentResponse {
Expand Down
27 changes: 13 additions & 14 deletions plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
Original file line number Diff line number Diff line change
Expand Up @@ -5320,8 +5320,9 @@ public void handle(ErrorCode errCode, Map data) {

private void handle(SecretHostGetMsg msg) {
SecretHostGetReply reply = new SecretHostGetReply();
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose()) || msg.getKeyVersion() == null) {
reply.setError(operr("vmUuid, purpose and keyVersion are required for get secret"));
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose()) ||
msg.getKeyVersion() == null || StringUtils.isBlank(msg.getUsageInstance())) {
reply.setError(operr("vmUuid, purpose, keyVersion and usageInstance are required for get secret"));
bus.reply(msg, reply);
return;
}
Expand All @@ -5331,7 +5332,7 @@ private void handle(SecretHostGetMsg msg) {
cmd.setVmUuid(msg.getVmUuid());
cmd.setPurpose(msg.getPurpose());
cmd.setKeyVersion(msg.getKeyVersion());
cmd.setUsageInstance(KVMConstant.HOST_SECRET_USAGE_INSTANCE_VTPM);
cmd.setUsageInstance(msg.getUsageInstance());
Map<String, String> headers = new HashMap<>();
headers.put(Constants.AGENT_HTTP_HEADER_RESOURCE_UUID, getSelf().getUuid());
Http<KVMAgentCommands.SecretHostGetResponse> http = new Http<>(url, cmd, KVMAgentCommands.SecretHostGetResponse.class);
Expand Down Expand Up @@ -5372,8 +5373,9 @@ private void handle(SecretHostDefineMsg msg) {
bus.reply(msg, reply);
return;
}
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose()) || msg.getKeyVersion() == null) {
reply.setError(operr("vmUuid, purpose and keyVersion are required for ensure secret"));
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose()) ||
msg.getKeyVersion() == null || StringUtils.isBlank(msg.getUsageInstance())) {
reply.setError(operr("vmUuid, purpose, keyVersion and usageInstance are required for ensure secret"));
bus.reply(msg, reply);
return;
}
Expand Down Expand Up @@ -5452,8 +5454,9 @@ private void handle(SecretHostDefineMsg msg) {
cmd.setVmUuid(msg.getVmUuid());
cmd.setPurpose(msg.getPurpose());
cmd.setKeyVersion(msg.getKeyVersion());
cmd.setSecretUuid(msg.getSecretUuid());
cmd.setDescription(msg.getDescription() != null ? msg.getDescription() : "");
cmd.setUsageInstance(KVMConstant.HOST_SECRET_USAGE_INSTANCE_VTPM);
cmd.setUsageInstance(msg.getUsageInstance());
Map<String, String> headers = new HashMap<>();
headers.put(Constants.AGENT_HTTP_HEADER_RESOURCE_UUID, getSelf().getUuid());
Http<KVMAgentCommands.SecretHostDefineResponse> http = new Http<>(url, cmd, KVMAgentCommands.SecretHostDefineResponse.class);
Expand Down Expand Up @@ -5486,13 +5489,9 @@ public Class<KVMAgentCommands.SecretHostDefineResponse> getReturnClass() {

private void handle(SecretHostDeleteMsg msg) {
SecretHostDeleteReply reply = new SecretHostDeleteReply();
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose())) {
reply.setError(operr("vmUuid and purpose are required for delete secret"));
bus.reply(msg, reply);
return;
}
if (msg.getKeyVersion() == null) {
reply.setError(operr("keyVersion is required for delete secret"));
if (StringUtils.isBlank(msg.getVmUuid()) || StringUtils.isBlank(msg.getPurpose()) ||
StringUtils.isBlank(msg.getUsageInstance()) || msg.getKeyVersion() == null) {
reply.setError(operr("vmUuid, purpose, keyVersion and usageInstance are required for delete secret"));
bus.reply(msg, reply);
return;
}
Expand All @@ -5502,7 +5501,7 @@ private void handle(SecretHostDeleteMsg msg) {
cmd.setVmUuid(msg.getVmUuid());
cmd.setPurpose(msg.getPurpose());
cmd.setKeyVersion(msg.getKeyVersion());
cmd.setUsageInstance(KVMConstant.HOST_SECRET_USAGE_INSTANCE_VTPM);
cmd.setUsageInstance(msg.getUsageInstance());
Map<String, String> headers = new HashMap<>();
headers.put(Constants.AGENT_HTTP_HEADER_RESOURCE_UUID, getSelf().getUuid());
Http<KVMAgentCommands.SecretHostDeleteResponse> http = new Http<>(url, cmd, KVMAgentCommands.SecretHostDeleteResponse.class);
Expand Down
Loading