Workflows for vSphere Virtual Machine Encryption
The sections below present vSphere API methods for key acquisition and encryption.
Set Up the Key Management Server Cluster
Before you can start encrypting virtual machines, you must set up the Key Management Server (KMS) cluster. This includes adding the KMS, establishing trust with the KMS, and setting the default KMS cluster. The KMS must support the KMIP (Key Management Interoperability Protocol) 1.1 standard, and it must be capable of acting as a symmetric key foundry and server.
Add Key Management Server(s) to Your Datacenter
Your organization’s security administrator may be responsible for this task. This person will need to provide the cluster name (if it already exists), the KMS server name, its IP address, its connection port number, and possibly a proxy address, proxy port number, KMS user name, and corresponding password.
The CryptoManager.java code to add a KMS and set the default KMS cluster appears in Example: CryptoManager Java program to add KMS and set default cluster. The user running this program must have Cryptographic operations.Manage key servers privileges.
Establish a Trusted Connection by Exchanging Certificates
There are four ways to establish trust between a KMS and vCenter Server. Different KMS vendors require one of these different methods. Java samples for methods 2 to 4 appear below Example: CryptoManager Java program to add KMS and set default cluster.
1
2
3
4
Example: CryptoManager Java program to add KMS and set default cluster
package com.vmware.general;
import com.vmware.common.annotations.Action;
import com.vmware.common.annotations.Option;
import com.vmware.common.annotations.Sample;
import com.vmware.connection.ConnectedVimServiceBase;
import com.vmware.vim25.CryptoKeyId;
import com.vmware.vim25.CryptoKeyResult;
import com.vmware.vim25.CryptoManagerKmipServerCertInfo;
import com.vmware.vim25.KeyProviderId;
import com.vmware.vim25.KmipServerInfo;
import com.vmware.vim25.KmipServerSpec;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.RuntimeFaultFaultMsg;
/**
 * CryptoManager. Demonstrates uses of the CryptoManager API. Parameters:
 * url      [required] : web service url, for example https://10.9.8.7/sdk
 * username [required] : username for the authentication
 * password [required] : corresponding password
 * Command line to run CryptoManager code:
 * run.bat com.vmware.general.CryptoManager --url webserviceurl --username name --password pass
 *                                       --kmsname kms --kmsip ipaddr --kmsclusterid providerId
 */
@Sample(name = "CryptoManager", description = "Demonstrates uses of the CryptoManager API")
public class CryptoManager extends ConnectedVimServiceBase {
  private ManagedObjectReference cryptoManager = null;
  private KmipServerSpec kmipSpec = null;
  private String kmsName;
  private String kmsIp;
  private int kmsPort = 5696; // default
  private String kmsClusterId;
 
   public void initCryptoManager() throws RuntimeFaultFaultMsg {
      if (serviceContent != null) {
         cryptoManager = serviceContent.getCryptoManager();
         if (cryptoManager == null) {
            throw new RuntimeFaultFaultMsg("CryptoManager could not be obtained", null);
         }
      } else {
         throw new RuntimeFaultFaultMsg("ServiceContent could not be obtained", null);
      }
   }
   public void registerKmipServer() throws RuntimeFaultFaultMsg {
      KmipServerInfo serverInfo = new KmipServerInfo(); // Create KMS info
      serverInfo.setName(kmsName); // Set the name of your KMS here
      serverInfo.setAddress(kmsIp); // Set the IP addr of your KMS
      serverInfo.setPort(kmsPort); // Set KMS port, if different from default
      KeyProviderId providerId = new KeyProviderId(); // Set the name of KMS cluster here
      providerId.setId("KMScluster");
      kmipSpec = new KmipServerSpec();
      kmipSpec.setInfo(serverInfo); // KMS spec with server and cluster ID
      kmipSpec.setClusterId(providerId);
      vimPort.registerKmipServer(cryptoManager, kmipSpec); // Register server
   }
   public void trustKmip() throws RuntimeFaultFaultMsg { // Get KMS certificate
      CryptoManagerKmipServerCertInfo certInfo = vimPort.retrieveKmipServerCert(cryptoManager, kmipSpec.getClusterId(), kmipSpec.getInfo());
      // Upload retrieved certificate to vCenter Server and trust it
      vimPort.uploadKmipServerCert(cryptoManager, kmipSpec.getClusterId(), certInfo.getCertificate());
   }
   public void establishTrust() throws RuntimeFaultFaultMsg {
      // Make KMS trust vCenter Server by uncommenting and calling one of these lines
      // - establishTrustUsingSelfSignedCert() - see Example: Trust with self-signed certificate or Root CA certificate for source code
      // - establishTrustUsingSignedCsr() - see Example: Trust with CSR then downloading KMS signed certificate for source code
      // - establishTrustUsingCertAndKey() - see Example: Trust by downloading KMS certificate and private key for source code
      trustKmip(); // Now make the vCenter Server trust KMS
   }
   public void setDefaultKmipCluster() throws RuntimeFaultFaultMsg {
      vimPort.markDefault(cryptoManager, kmipSpec.getClusterId()); // Mark cluster as default
   }
   public void generateNewKey() throws RuntimeFaultFaultMsg {
      CryptoKeyResult keyResult = vimPort.generateKey(cryptoManager, kmipSpec.getClusterId());
      CryptoKeyId keyId = keyResult.getKeyId(); // Generate new key for encryption
   }
   @Action
   public void action() throws RuntimeFaultFaultMsg {
      initCryptoManager();
      registerKmipServer();
      establishTrust();
      setDefaultKmipCluster();
      generateNewKey();
   }
   @Option(name = "kmsname", description = "Name of the KMS", required = true)
   public void setKMSName(String name) {
      this.kmsName = name;
   }
   @Option(name = "kmsip", description = "IP address of the KMS", required = true)
   public void setKMSIp(String ip) {
      this.kmsIp = ip;
   }
   @Option(name = "kmsport", description = "KMS port", required = false)
   public void setKMSPort(String port) {
      this.kmsPort = Integer.parseInt(port);
   }
   @Option(name = "kmsclusterid", description = "KMS cluster Id", required = true)
   public void setKMSClusterId(String clusterId) {
      this.kmsClusterId = clusterId;
   }
}
 
This example method uploads a self-signed vCenter certificate, or the Root CA certificate, to the KMS.
Example: Trust with self-signed certificate or Root CA certificate
public void establishTrustUsingSelfSignedCert() throws RuntimeFaultFaultMsg {
   // Generate self-signed cert, or obtain the Root CA certificate
   String selfSignedCert = vimPort.generateSelfSignedClientCert(cryptoManager, kmipSpec.getClusterId());
   // Follow steps for KMS to trust self-signed or Root CA cert, update vCenter to use it
   vimPort.updateSelfSignedClientCert(cryptoManager, kmipSpec.getClusterId(), selfSignedCert);
}
 
This example method generates a CSR and downloads the KMS signed certificate onto vCenter Server.
Example: Trust with CSR then downloading KMS signed certificate
public void establishTrustUsingSignedCsr() throws RuntimeFaultFaultMsg {
   // Generate a Certificate Signing Request
   String csr = vimPort.generateClientCsr(cryptoManager, kmipSpec.getClusterId());
   String signedCert = null;
   // Follow steps for your KMS to sign CSR and get the signedCert to update on vCenter
   vimPort.updateKmsSignedCsrClientCert(cryptoManager, kmipSpec.getClusterId(), signedCert);
}
This example method downloads a certificate and private key generated by the KMS to vCenter Server.
Example: Trust by downloading KMS certificate and private key
public void establishTrustUsingCertAndKey() throws RuntimeFaultFaultMsg {
   String certFromKms = null;
   String privateKeyKms = null;
   // Follow steps for KMS to generate certificate and private key (certFromKms, privateKeyKms)
   vimPort.uploadClientCert(cryptoManager, kmipSpec.getClusterId(), certFromKms, privateKeyKms);
}
 
Create an Encryption Storage Policy
Before any virtual machines can be encrypted, vCenter Server must contain an encryption storage policy. The policy only needs to be created once; it can be assigned to any virtual machines that you want to encrypt.
Example: Java program to set storage policy for encryption
package com.vmware.spbm.samples;
import java.util.ArrayList;
import java.util.List;
import com.vmware.common.annotations.Action;
import com.vmware.common.annotations.Option;
import com.vmware.common.annotations.Sample;
import com.vmware.pbm.InvalidArgumentFaultMsg;
import com.vmware.pbm.PbmCapabilityConstraintInstance;
import com.vmware.pbm.PbmCapabilityInstance;
import com.vmware.pbm.PbmCapabilityMetadata;
import com.vmware.pbm.PbmCapabilityMetadataPerCategory;
import com.vmware.pbm.PbmCapabilityProfileCreateSpec;
import com.vmware.pbm.PbmCapabilityPropertyInstance;
import com.vmware.pbm.PbmCapabilityPropertyMetadata;
import com.vmware.pbm.PbmCapabilitySubProfile;
import com.vmware.pbm.PbmCapabilitySubProfileConstraints;
import com.vmware.pbm.PbmCapabilityVendorNamespaceInfo;
import com.vmware.pbm.PbmCapabilityVendorResourceTypeInfo;
import com.vmware.pbm.PbmDuplicateNameFaultMsg;
import com.vmware.pbm.PbmFaultProfileStorageFaultFaultMsg;
import com.vmware.pbm.PbmProfileId;
import com.vmware.pbm.PbmServiceInstanceContent;
import com.vmware.spbm.connection.ConnectedServiceBase;
import com.vmware.spbm.connection.helpers.PbmUtil;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.RuntimeFaultFaultMsg;
/**
 * CreateVMEncryptionProfile
 * Create new Storage Profile with one rule-set based on vmwarevmcrypt capabilities. Parameters:
 * vcurl       [required] : web service url, for example https://10.9.8.7/sdk
 * username    [required] : username for the authentication
 * password    [required] : corresponding password
 * profilename [required] : name of the storage profile
 * Command Line:
 * run.bat com.vmware.spbm.samples.CreateVMEncryptionProfile --vcurl [webserviceurl]
 *              --username [username] --password [password] --profilename [Storage Profile Name]
 */
@Sample(name = "CreateVMEncryptionProfile", description = "Create a new storage profile with one rule-set based on vmwarevmcrypt capabilities.")
public class CreateVMEncryptionProfile extends ConnectedServiceBase {
   private PbmServiceInstanceContent spbmsc;
   private String profileName;
 
   // Build capability instance based on capability name associated with vmwarevmcrypt provider
   PbmCapabilityInstance buildCapability(String capabilityName, List<PbmCapabilityMetadataPerCategory> metadata) throws InvalidArgumentFaultMsg {
      // Create Property Instance with capability vmwarevmcrypt
      PbmCapabilityMetadata capabilityMeta = PbmUtil.getCapabilityMeta(capabilityName,metadata);
      if (capabilityMeta == null)
         throw new InvalidArgumentFaultMsg("Specified Capability does not exist", null);
      // Create and associate Property Instances with a Rule
      PbmCapabilityConstraintInstance rule = new PbmCapabilityConstraintInstance();
      for (PbmCapabilityPropertyMetadata propMeta : capabilityMeta.getPropertyMetadata()) {
         PbmCapabilityPropertyInstance prop = new PbmCapabilityPropertyInstance();
         prop.setId(propMeta.getId());
         prop.setValue(propMeta.getDefaultValue());
         rule.getPropertyInstance().add(prop);
      }
      // Associate Rule with a Capability Instance
      PbmCapabilityInstance capability = new PbmCapabilityInstance();
      capability.setId(capabilityMeta.getId());
      capability.getConstraint().add(rule);
      return capability;
   }
   @Action
   public void createProfile() throws RuntimeFaultFaultMsg,
         com.vmware.pbm.RuntimeFaultFaultMsg, InvalidArgumentFaultMsg,
         PbmDuplicateNameFaultMsg, PbmFaultProfileStorageFaultFaultMsg {
      // Get PBM Profile Manager & Associated Capability Metadata
      spbmsc = connection.getPbmServiceContent();
      ManagedObjectReference profileMgr = spbmsc.getProfileManager();
      // Step 1: Check if there is a vmwarevmcrypt Provider
      Boolean encryptionCapable = false;
      List<PbmCapabilityVendorResourceTypeInfo> vendorInfo = connection
            .getPbmPort().pbmFetchVendorInfo(profileMgr, null);
      for (PbmCapabilityVendorResourceTypeInfo vendor : vendorInfo)
         for (PbmCapabilityVendorNamespaceInfo vnsi : vendor .getVendorNamespaceInfo())
            if (vnsi.getNamespaceInfo().getNamespace().equals("vmwarevmcrypt")) {
               encryptionCapable = true;
               break;
            }
      if (!encryptionCapable)
         throw new RuntimeFaultFaultMsg(
               "Cannot create storage profile. 'vmwarevmcrypt' Provider not found.", null);
      // Step 2: Get PBM Supported Capability Metadata
      List<PbmCapabilityMetadataPerCategory> metadata = connection .getPbmPort().pbmFetchCapabilityMetadata(profileMgr, PbmUtil.getStorageResourceType(), "com.vmware.iofilters");
      // Step 3: Add Provider Specific Capabilities
      List<PbmCapabilityInstance> capabilities = new ArrayList<PbmCapabilityInstance>();
      capabilities.add(buildCapability("vmwarevmcrypt@ENCRYPTION", metadata));
      // Step 4: Add Capabilities to a RuleSet
      PbmCapabilitySubProfile ruleSet = new PbmCapabilitySubProfile();
      ruleSet.getCapability().addAll(capabilities);
      // Step 5: Add Rule-Set to Capability Constraints
      PbmCapabilitySubProfileConstraints constraints = new PbmCapabilitySubProfileConstraints();
      ruleSet.setName("Rule-Set " + (constraints.getSubProfiles().size() + 1));
      constraints.getSubProfiles().add(ruleSet);
      // Step 6: Build Capability-Based Profile
      PbmCapabilityProfileCreateSpec spec = new PbmCapabilityProfileCreateSpec();
      spec.setName(profileName);
      spec.setDescription("Storage Profile in SDK. Rule based on Encryption capability");
      spec.setResourceType(PbmUtil.getStorageResourceType());
      spec.setConstraints(constraints);
      // Step 7: Create Storage Profile
      PbmProfileId profile = connection.getPbmPort().pbmCreate(profileMgr, spec);
      System.out.println("Profile " + profileName + " with ID: " + profile.getUniqueId());
   }
   @Option(name = "profilename", description = "Name of the storage profile", required = true)
   public void setProfileName(String profileName) {
      this.profileName = profileName;
   }
}
 
Create an Encrypted Virtual Machine
The Web Services SDK provides Java and C# code to create a virtual machine. The Java code can be modified to create an encrypted virtual machine. Steps below show how to implement virtual machine encryption in the VMCreate.java sample program. The crypto property in VirtualMachineConfigSpec should be set to CryptoSpecEncrypt, and an encryption key provided. The storage profile must have been previously set to specify encryption. If the CryptoSpec is unset, but a storage profile with encryption is set, vCenter Server automatically generates new keys and sets CryptoSpec, if a default KMS has been configured.
To enhance the com.vmware.spbm.samples.VMCreate program for encryption, follow these steps:
1
import com.vmware.vim25.CryptoKeyId;
import com.vmware.vim25.CryptoSpecEncrypt;
import com.vmware.vim25.KeyProviderId;
import com.vmware.vim25.VirtualDeviceConfigSpecBackingSpec;
2
private CryptoKeyId cryptoKeyId;
private String keyId;
private String providerId;
3
In the createVirtualDisk() function, add the following code after the first (blue) line:
diskSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
if ((keyId != null) && (providerId != null)) {
   CryptoSpecEncrypt cSpec = new CryptoSpecEncrypt();
   VirtualDeviceConfigSpecBackingSpec backingSpec = new VirtualDeviceConfigSpecBackingSpec();
   cSpec.setCryptoKeyId(buildCryptoKeyId());
   backingSpec.setCrypto(cSpec);
   diskSpec.setBacking(backingSpec);
}
4
In the createVmConfigSpec() function, add the following code after the first (blue) line:
VirtualMachineConfigSpec configSpec = new VirtualMachineConfigSpec();
if ((keyId != null) && (providerId != null)) {
   CryptoSpecEncrypt cryptoSpecForVMHome = new CryptoSpecEncrypt();
   cryptoSpecForVMHome.setCryptoKeyId(buildCryptoKeyId());
   configSpec.setCrypto(cryptoSpecForVMHome);
}
5
@Option(name = "keyid", description = "Key Id", required = false)
public void setKeyId(String kid) {
   this.keyId = kid;
}
@Option(name = "providerid", description = "Cluster/Provider Id", required = false)
public void setProviderId(String pid) {
   this.providerId = pid;
}
The SPBM sample code is in the Storage Policy SDK, not in the vSphere Web Services SDK.
Clone an Encrypted Virtual Machine
Set the crypto property in RelocateSpec at cloneSpec.location. The virtual machine must be powered off, with no existing snapshots. The encrypted virtual machine will be cloned, still encrypted.
Example: Clone an encrypted virtual machine
// Step 5: Create Specs
VirtualMachineRelocateSpec relocSpec = new VirtualMachineRelocateSpec();
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
VirtualMachineConfigSpec configSpec = new VirtualMachineConfigSpec();
// Step 6: Associate Storage Profile
relocSpec.getProfile().add(getVMDefinedProfileSpec(profileName));
cloneSpec.setConfig(configSpec);
cloneSpec.setLocation(relocSpec);
cloneSpec.setPowerOn(false);
cloneSpec.setTemplate(false);
// Step 7: Clone VM
ManagedObjectReference
cloneTask = connection.getVimPort().cloneVMTask(vmRef, vmFolderRef, cloneName, cloneSpec);
 
Encrypt an Existing Virtual Machine or Disk
First set the crypto property in the VirtualMachineConfigSpec to CryptoSpecEncrypt and provide a key. The virtual machine must be powered off, with no existing snapshots.
Storage profiles must also be set to specify encryption. If the CryptoSpec is unset, but a storage profile with encryption is set, the vCenter Server automatically generates new keys and sets CryptoSpec, if the default KMS cluster has been configured.
Example: Encrypt a virtual machine based on storage profile
void Encrypt() throws Exception {
   // Create VirtualMachineConfigSpec
   VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
   // Create VirtualDeviceConfigSpec
   VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
   // Get VirtualMachineProfileSpec for new encryption profile and name it encryptionProfile
   VirtualMachineProfileSpec encryptionProfile = new VirtualMachineDefinedProfileSpec();
   // Get VirtualDisk for disk to be reconfigured as in com.vmware.vm.VMReconfig, name it disk
   diskSpec.setDevice(disk);
   diskSpec.setOperation(VirtualDeviceConfigSpecOperation.EDIT);
   // Add encryption profile to VirtualDeviceConfigSpec
   diskSpec.getProfile().add(encryptionProfile);
   // Create CryptoSpec for encryption
   // Get Key Id from CryptoManager as keyId
   // See CryptoManager for details on generating or retrieving CryptoKeyId
   CryptoSpecEncrypt cryptoSpec = new CryptoSpecEncrypt();
   cryptoSpec.setCryptoKeyId(keyId);
   // Add CryptoSpecEncrypt to diskSpec backing
   VirtualDeviceConfigSpecBackingSpec backingSpec = new VirtualDeviceConfigSpecBackingSpec();
   backingSpec.setCrypto(cryptoSpec);
   diskSpec.setBacking(backingSpec);
   // When encrypting a VirtualDisk, the VM home needs to be encrypted also.
   // You can choose the same key to encrypt VM home and virtual disk, or use different keys.
   // Set cryptoSpec and profile for encrypting virtual machine home.
   vmConfigSpec.setCrypto(cryptoSpec);
   vmConfigSpec.getVmProfile().add(encryptionProfile);
   // Set the device changes
   vmConfigSpec.getDeviceChange().add(diskSpec);
   // Issue reconfigure - See reConfig() in com.vmware.vm.VMReconfig for how to reconfigure VM
}
 
Decrypt an Encrypted Virtual Machine or Disk
This is similar to encrypting an existing virtual machine, but with a different CryptoSpec. First set the crypto property in the VirtualMachineConfigSpec to CryptoSpecDecrypt. The virtual machine must be powered off, and the storage profiles must be set not to specify encryption.
If the CryptoSpec is unset, but a storage profile without encryption is set, the vCenter Server sets CryptoSpecDecrypt. The ConfigSpec.crypto parameter must be set explicitly – only encryption is deduced from the storage profile.
Example: Decrypt a virtual machine based on storage profile
void Decrypt() throws Exception {
   // Create VirtualMachineConfigSpec
   VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
   // Create VirtualDeviceConfigSpec
   VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
   // Create Empty VirtualMachineProfileSpec for decryption
   VirtualMachineProfileSpec emptyProfile = new VirtualMachineEmptyProfileSpec();
   // Get VirtualDisk for disk to be reconfigured as in com.vmware.vm.VMReconfig, name it disk.
   diskSpec.setDevice(disk);
   diskSpec.setOperation(VirtualDeviceConfigSpecOperation.EDIT);
   // Remove any encryption profile set for the disk
   diskSpec.getProfile().add(emptyProfile);
   // Create CryptoSpec for decryption
   CryptoSpecDecrypt cryptoSpec = new CryptoSpecDecrypt();
   // Add CryptoSpecEncrypt to diskSpec backing
   VirtualDeviceConfigSpecBackingSpec backingSpec = new VirtualDeviceConfigSpecBackingSpec();
   backingSpec.setCrypto(cryptoSpec);
   diskSpec.setBacking(backingSpec);
   // Decrypting virtual machine home is not necessary when decrypting a virtual disk.
   // If no encrypted disk is present on the virtual machine after the above disk is decrypted,
   // you can choose to decrypt virtual machine home.
   // Set cryptoSpec and profile for decrypting virtual machine home
   vmConfigSpec.setCrypto(cryptoSpec);
   vmConfigSpec.getVmProfile().add(emptyProfile);
   // Set the device changes
   vmConfigSpec.getDeviceChange().add(diskSpec);
   // Issue reconfigure - See reConfig() in com.vmware.vm.VMReconfig for how to reconfigure VM
}
 
Encrypt Using Different Keys
This method shows how to use two different keys to encrypt the virtual machine (VM home) and its disk.
Example: Different encryption keys for VM home and virtual disk
void EncryptUsingDifferentKeys() throws Exception {
   // Create VirtualMachineConfigSpec and VirtualDeviceConfigSpec
   VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
   VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
   // Get VirtualMachineProfileSpec for encryption profile you created and name it
   VirtualMachineProfileSpec encryptionProfile = new VirtualMachineDefinedProfileSpec();
   // Get VirtualDisk for disk to be reconfigured as shown in VMReconfig and name it
   diskSpec.setDevice(disk);
   diskSpec.setOperation(VirtualDeviceConfigSpecOperation.EDIT);
   // Add encryption profile to VirtualDeviceConfigSpec
   diskSpec.getProfile().add(encryptionProfile);
   // Create CryptoSpec for disk encryption and get KeyId from from CryptoManager
   // See CryptoManager for details on generating or retrieving CryptoKeyId
   CryptoSpecEncrypt cryptoSpecForDisk = new CryptoSpecEncrypt();
   cryptoSpecForDisk.setCryptoKeyId(keyIdForDiskEncryption);
   // Add CryptoSpecEncrypt to diskSpec backing
   VirtualDeviceConfigSpecBackingSpec backingSpec = new VirtualDeviceConfigSpecBackingSpec();
   backingSpec.setCrypto(cryptoSpecForDisk);
   diskSpec.setBacking(backingSpec);
   // When encrypting a VirtualDisk, the virtual machine home must also be encrypted.
   // You can choose the same key to encrypt VM home and disk, or use different keys.
   // Create CryptoSpec for VM Home encryption and get KeyId from CryptoManager.
   CryptoSpecEncrypt cryptoSpecForVMHome = new CryptoSpecEncrypt();
   cryptoSpecForVMHome.setCryptoKeyId(keyIdForVMHomeEncryption);
   // Set cryptoSpec and profile for encrypting virtual machine home
   vmConfigSpec.setCrypto(cryptoSpecForVMHome);
   vmConfigSpec.getVmProfile().add(encryptionProfile);
   // Set the device changes
   vmConfigSpec.getDeviceChange().add(diskSpec);
}
 
Recrypting Encrypted Virtual Machines
Currently it is not possible to recrypt virtual machines using the vSphere Web Client. Only the vSphere API can accomplish this task. Deep recrypt replaces all keys, rewriting encrypted data in a powered-off virtual machine and its disks. Shallow recrypt replaces only top-level keys and is comparatively fast. For details on generating or retrieving the CryptoKeyId, see CryptoManager code in Example: CryptoManager Java program to add KMS and set default cluster.
Recrypt Only Key Encryption Keys
For shallow recrypt, which affects only the key encryption keys (KEKs), set the crypto property in the VirtualMachineConfigSpec to CryptoSpecShallowRecrypt and call the Reconfigure method.
Example: Shallow Recrypt
void ShallowRecrypt() throws Exception {
    // Shallow recrypt follows the same flow as encrypt. The two differences are:
    // - Instead of using a new encryption profile, just get the previously
    //   applied profile from the virtual machine to be reconfigured and use it.
    // - The type of CryptoSpec object created is CryptoSpecShallowRecrypt()
    // Create CryptoSpec for shallow recrypt
    // Get Key Id from CryptoManager as newKeyId
    CryptoSpecShallowRecrypt cryptoSpec = new CryptoSpecShallowRecrypt();
    cryptoSpec.setNewKeyId(newKeyId);
    // Follow steps from Encrypt()
}
 
Shallow recrypt can be done with the virtual machine powered on. Deep recrypt requires power off.
Recrypt Both Key and Disk Encryption Keys
For deep recrypt, which affects both KEKs and disk encryption keys (DEKs), set the crypto property in the VirtualMachineConfigSpec to CryptoSpecDeepRecrypt and call the Reconfigure method.
Example: Deep Recrypt
void DeepRecrypt() throws Exception {
    // Deep recrypt follows the same flow as encrypt. The two differences are:
    // - Instead of using a new encryption profile, just get the previously
    //   applied profile from the virtual machine to be reconfigured and use it.
    // - The type of CryptoSpec object created is CryptoSpecDeepRecrypt()
    // Create CryptoSpec for deep recrypt
    // Get Key Id from CryptoManager as newKeyId
    CryptoSpecDeepRecrypt cryptoSpec = new CryptoSpecDeepRecrypt();
    cryptoSpec.setNewKeyId(newKeyId);
    // Follow steps from Encrypt()
}
 
Encrypted vSphere vMotion
When virtual machines and data move across the network, all sensitive data remain encrypted.
Enable Encrypted vMotion
The enumeration VirtualMachineConfigSpecEncryptedVMotionModes controls whether encrypted vMotion is disabled, opportunistic (fall back to unencrypted vMotion if necessary, the default option), or required.
If encrypted vMotion is required, or opportunistic and available, the vCenter Server can migrate either encrypted or unencrypted virtual machines within a disk cluster, or from one disk cluster to another using Storage vMotion.
In this release, vMotion across vCenter Servers is not supported for encrypted virtual machines.
Virtual Disk Manager
The following methods in managed object VirtualDiskManager are affected by encryption:
copyVirtualDisk – If the source disk is encrypted, its copied disk is encrypted with the same key, regardless of the crypto spec. When calling copyVirtualDisk_Task on vCenter Server, do not specify the destSpec parameter, which throws a Not Implemented fault; destSpec is supported only on ESXi hosts.
createVirtualDisk – Given a valid crypto spec, this task directly creates an encrypted virtual disk.
moveVirtualDisk – An encrypted virtual disk cannot be moved to an unencrypted virtual machine.
createChildDisk – The child disk of an encrypted disk remains encrypted with the same key.
reparentDisks – Encrypted child disk cannot be reparented to a new disk that is not in the same disk chain.