11package org .zstack .kvm .tpm ;
22
33import org .springframework .beans .factory .annotation .Autowired ;
4+ import org .zstack .compute .vm .devices .TpmEncryptedResourceKeyBackend ;
45import org .zstack .core .Platform ;
6+ import org .zstack .core .cloudbus .CloudBus ;
7+ import org .zstack .core .cloudbus .CloudBusCallBack ;
58import org .zstack .core .db .DatabaseFacade ;
69import org .zstack .core .db .Q ;
710import org .zstack .core .db .SQL ;
11+ import org .zstack .core .workflow .SimpleFlowChain ;
812import 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 ;
917import 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 ;
1022import org .zstack .header .vm .PreVmInstantiateResourceExtensionPoint ;
1123import org .zstack .header .vm .VmInstanceSpec ;
1224import org .zstack .header .vm .VmInstantiateResourceException ;
2436
2537import java .sql .Timestamp ;
2638import java .time .Instant ;
39+ import java .util .Map ;
2740
2841import 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 ) {
0 commit comments