Skip to content

Commit be47876

Browse files
author
gitlab
committed
Merge branch 'zsv-ldap@@2' into 'feature-zsv-5.0.0-vm-support-vtpm-and-secuceboot'
<feature>[compute]: prepare DEK on instantiating VM resource See merge request zstackio/zstack!9381
2 parents 55a86de + 0eecfd9 commit be47876

6 files changed

Lines changed: 171 additions & 20 deletions

File tree

compute/src/main/java/org/zstack/compute/vm/devices/DummyTpmEncryptedResourceKeyBackend.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public String findKeyProviderUuidByTpm(String tpmUuid) {
2323
return null;
2424
}
2525

26+
@Override
27+
public String findKeyProviderNameByTpm(String tpmUuid) {
28+
return null;
29+
}
30+
2631
@Override
2732
public void cloneEncryptedResourceKey(CloneEncryptedResourceKeyContext context, Completion completion) {
2833
// do nothing

compute/src/main/java/org/zstack/compute/vm/devices/TpmEncryptedResourceKeyBackend.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public interface TpmEncryptedResourceKeyBackend {
2525
*/
2626
String findKeyProviderUuidByTpm(String tpmUuid);
2727

28+
/**
29+
* maybe null (when crypto module is not installed)
30+
*/
31+
String findKeyProviderNameByTpm(String tpmUuid);
32+
2833
static class CloneEncryptedResourceKeyContext {
2934
public String srcTpmUuid;
3035
public String dstTpmUuid;

compute/src/main/java/org/zstack/compute/vm/devices/VmTpmExtensions.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,22 @@ public void afterBuildVmSpec(VmInstanceSpec spec) {
9999
spec.setNvRamSpec(nvRamSpec);
100100
}
101101

102-
if (tpmUuid != null && (spec.getDevicesSpec() == null || spec.getDevicesSpec().getTpm() == null)) {
103-
VmDevicesSpec devicesSpec = spec.getDevicesSpec() == null ? new VmDevicesSpec() : spec.getDevicesSpec();
104-
spec.setDevicesSpec(devicesSpec);
102+
if (tpmUuid != null) {
103+
VmDevicesSpec devicesSpec = spec.getDevicesSpec();
104+
if (devicesSpec == null) {
105+
devicesSpec = new VmDevicesSpec();
106+
spec.setDevicesSpec(devicesSpec);
107+
}
108+
109+
TpmSpec tpmSpec = devicesSpec.getTpm();
110+
if (tpmSpec == null) {
111+
tpmSpec = new TpmSpec();
112+
devicesSpec.setTpm(tpmSpec);
113+
}
105114

106-
devicesSpec.setTpm(new TpmSpec());
107-
devicesSpec.getTpm().setEnable(true);
108-
devicesSpec.getTpm().setKeyProviderUuid(resourceKeyBackend.findKeyProviderUuidByTpm(tpmUuid));
115+
tpmSpec.setEnable(true);
116+
tpmSpec.setTpmUuid(tpmUuid);
117+
tpmSpec.setKeyProviderUuid(resourceKeyBackend.findKeyProviderUuidByTpm(tpmUuid));
109118
}
110119
}
111120
}

header/src/main/java/org/zstack/header/tpm/entity/TpmSpec.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package org.zstack.header.tpm.entity;
22

3+
import org.zstack.header.rest.APINoSee;
34
import org.zstack.utils.StringDSL;
45

56
public class TpmSpec {
67
private boolean enable = true;
8+
private String tpmUuid;
79
private String keyProviderUuid;
10+
@APINoSee
11+
private String secretUuid;
812

913
public boolean isEnable() {
1014
return enable;
@@ -14,6 +18,14 @@ public void setEnable(boolean enable) {
1418
this.enable = enable;
1519
}
1620

21+
public String getTpmUuid() {
22+
return tpmUuid;
23+
}
24+
25+
public void setTpmUuid(String tpmUuid) {
26+
this.tpmUuid = tpmUuid;
27+
}
28+
1729
public String getKeyProviderUuid() {
1830
return keyProviderUuid;
1931
}
@@ -22,6 +34,14 @@ public void setKeyProviderUuid(String keyProviderUuid) {
2234
this.keyProviderUuid = keyProviderUuid;
2335
}
2436

37+
public String getSecretUuid() {
38+
return secretUuid;
39+
}
40+
41+
public void setSecretUuid(String secretUuid) {
42+
this.secretUuid = secretUuid;
43+
}
44+
2545
public static TpmSpec __example__() {
2646
TpmSpec tpm = new TpmSpec();
2747
tpm.setKeyProviderUuid(StringDSL.createFixedUuid("keyProviderUuid"));

plugin/kvm/src/main/java/org/zstack/kvm/tpm/KvmTpmExtensions.java

Lines changed: 117 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
package org.zstack.kvm.tpm;
22

33
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.zstack.compute.vm.devices.TpmEncryptedResourceKeyBackend;
45
import org.zstack.core.Platform;
6+
import org.zstack.core.cloudbus.CloudBus;
7+
import org.zstack.core.cloudbus.CloudBusCallBack;
58
import org.zstack.core.db.DatabaseFacade;
69
import org.zstack.core.db.Q;
710
import org.zstack.core.db.SQL;
11+
import org.zstack.core.workflow.SimpleFlowChain;
812
import org.zstack.header.core.Completion;
13+
import org.zstack.header.core.workflow.FlowDoneHandler;
14+
import org.zstack.header.core.workflow.FlowErrorHandler;
15+
import org.zstack.header.core.workflow.FlowTrigger;
16+
import org.zstack.header.core.workflow.NoRollbackFlow;
917
import org.zstack.header.errorcode.ErrorCode;
18+
import org.zstack.header.host.HostConstant;
19+
import org.zstack.header.message.MessageReply;
20+
import org.zstack.header.secret.SecretHostDefineMsg;
21+
import org.zstack.header.secret.SecretHostDefineReply;
1022
import org.zstack.header.vm.PreVmInstantiateResourceExtensionPoint;
1123
import org.zstack.header.vm.VmInstanceSpec;
1224
import org.zstack.header.vm.VmInstantiateResourceException;
@@ -24,6 +36,7 @@
2436

2537
import java.sql.Timestamp;
2638
import java.time.Instant;
39+
import java.util.Map;
2740

2841
import static org.zstack.kvm.KVMConstant.*;
2942

@@ -35,6 +48,10 @@ public class KvmTpmExtensions implements KVMStartVmExtensionPoint,
3548
private KvmSecureBootExtensions secureBootExtensions;
3649
@Autowired
3750
private DatabaseFacade databaseFacade;
51+
@Autowired
52+
private TpmEncryptedResourceKeyBackend resourceKeyBackend;
53+
@Autowired
54+
private CloudBus bus;
3855

3956
private final Object hostFileLock = new Object();
4057

@@ -47,6 +64,7 @@ public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAg
4764

4865
TpmTO tpm = new TpmTO();
4966
tpm.setKeyProviderUuid(devicesSpec.getTpm().getKeyProviderUuid());
67+
tpm.setSecretUuid(devicesSpec.getTpm().getSecretUuid());
5068
tpm.setInstallPath(buildTpmStateFilePath(cmd.getVmInstanceUuid()));
5169
cmd.setTpm(tpm);
5270

@@ -91,34 +109,119 @@ public void preBeforeInstantiateVmResource(VmInstanceSpec spec) throws VmInstant
91109
// do-nothing
92110
}
93111

94-
@Override
95-
public void preInstantiateVmResource(VmInstanceSpec spec, Completion completion) {
96-
prepareTpmStateHostFileOnHost(spec, completion);
97-
}
98-
99-
static class PrepareTpmStateHostFileContext {
112+
static class PreInstantiateVmResourceContext {
100113
String hostUuid;
101114
String vmUuid;
102-
103-
// whether the NvRam is on the same host as before
104-
boolean sameHost = false;
105-
VmHostFileVO tpmStateFile;
115+
String tpmUuid;
116+
String providerName;
117+
String dekBase64; // secret key
106118
}
107119

108-
private void prepareTpmStateHostFileOnHost(VmInstanceSpec spec, Completion completion) {
120+
@Override
121+
@SuppressWarnings("rawtypes")
122+
public void preInstantiateVmResource(VmInstanceSpec spec, Completion completion) {
109123
final VmDevicesSpec devicesSpec = spec.getDevicesSpec();
110124
if (devicesSpec == null || devicesSpec.getTpm() == null || !devicesSpec.getTpm().isEnable()) {
111125
completion.success();
112126
return;
113127
}
114128

115-
PrepareHostFileContext context = new PrepareHostFileContext();
129+
PreInstantiateVmResourceContext context = new PreInstantiateVmResourceContext();
116130
context.hostUuid = spec.getDestHost().getUuid();
117131
context.vmUuid = spec.getVmInventory().getUuid();
118-
context.type = VmHostFileType.TpmState;
119-
secureBootExtensions.prepareHostFileOnHost(context, completion);
132+
context.tpmUuid = spec.getDevicesSpec().getTpm().getTpmUuid();
133+
context.providerName = resourceKeyBackend.findKeyProviderNameByTpm(context.tpmUuid);
134+
135+
final SimpleFlowChain chain = new SimpleFlowChain();
136+
chain.setName("prepare-tpm-resources-for-vm-" + spec.getVmInventory().getUuid());
137+
chain.then(new NoRollbackFlow() {
138+
String __name__ = "prepare-tpm-state-file-on-host";
139+
140+
@Override
141+
public void run(FlowTrigger trigger, Map data) {
142+
PrepareHostFileContext innerContext = new PrepareHostFileContext();
143+
innerContext.hostUuid = context.hostUuid;
144+
innerContext.vmUuid = context.vmUuid;
145+
innerContext.type = VmHostFileType.TpmState;
146+
secureBootExtensions.prepareHostFileOnHost(innerContext, new Completion(trigger) {
147+
@Override
148+
public void success() {
149+
trigger.next();
150+
}
151+
152+
@Override
153+
public void fail(ErrorCode errorCode) {
154+
trigger.fail(errorCode);
155+
}
156+
});
157+
}
158+
}).then(new NoRollbackFlow() {
159+
String __name__ = "create-dek";
160+
161+
@Override
162+
public boolean skip(Map data) {
163+
return context.providerName == null;
164+
}
165+
166+
@Override
167+
public void run(FlowTrigger trigger, Map data) {
168+
// TODO create DEK
169+
context.dekBase64 = Platform.getUuid();
170+
trigger.next();
171+
}
172+
}).then(new NoRollbackFlow() {
173+
String __name__ = "define-secret-on-host";
174+
175+
@Override
176+
public boolean skip(Map data) {
177+
logger.warn("This is for test only, and coming soon"); // TODO
178+
return true;
179+
}
180+
181+
@Override
182+
public void run(FlowTrigger trigger, Map data) {
183+
SecretHostDefineMsg innerMsg = new SecretHostDefineMsg();
184+
innerMsg.setHostUuid(context.hostUuid);
185+
innerMsg.setVmUuid(context.vmUuid);
186+
innerMsg.setDekBase64(context.dekBase64);
187+
innerMsg.setPurpose("vtpm");
188+
innerMsg.setProviderName(context.providerName);
189+
innerMsg.setDescription("Define secret for VM " + context.vmUuid);
190+
bus.makeTargetServiceIdByResourceUuid(innerMsg, HostConstant.SERVICE_ID, innerMsg.getHostUuid());
191+
bus.send(innerMsg, new CloudBusCallBack(trigger) {
192+
@Override
193+
public void run(MessageReply reply) {
194+
if (reply.isSuccess()) {
195+
SecretHostDefineReply r = reply.castReply();
196+
spec.getDevicesSpec().getTpm().setSecretUuid(r.getSecretUuid());
197+
trigger.next();
198+
} else {
199+
trigger.fail(reply.getError());
200+
}
201+
}
202+
});
203+
}
204+
}).done(new FlowDoneHandler(completion) {
205+
@Override
206+
public void handle(Map data) {
207+
completion.success();
208+
}
209+
}).error(new FlowErrorHandler(completion) {
210+
@Override
211+
public void handle(ErrorCode errCode, Map data) {
212+
completion.fail(errCode);
213+
}
214+
}).start();
120215
}
121216

217+
static class PrepareTpmStateHostFileContext {
218+
String hostUuid;
219+
String vmUuid;
220+
221+
// whether the NvRam is on the same host as before
222+
boolean sameHost = false;
223+
VmHostFileVO tpmStateFile;
224+
}
122225

123226
@Override
124227
public void preReleaseVmResource(VmInstanceSpec spec, Completion completion) {

plugin/kvm/src/main/java/org/zstack/kvm/tpm/TpmTO.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
public class TpmTO implements Serializable {
66
private String keyProviderUuid;
7+
private String secretUuid;
78
private String installPath;
89

910
public String getKeyProviderUuid() {
@@ -14,6 +15,14 @@ public void setKeyProviderUuid(String keyProviderUuid) {
1415
this.keyProviderUuid = keyProviderUuid;
1516
}
1617

18+
public String getSecretUuid() {
19+
return secretUuid;
20+
}
21+
22+
public void setSecretUuid(String secretUuid) {
23+
this.secretUuid = secretUuid;
24+
}
25+
1726
public String getInstallPath() {
1827
return installPath;
1928
}

0 commit comments

Comments
 (0)