vmsiul
Enthusiast
Enthusiast

vRA 8.6 | Any way to enable Virtualization Based Security (VBS) at the VM level?

Jump to solution

Hello, 

We are running into a bit of an special request, we need to enable Virtualization Based Security at a VM level (not windows). 

vmsiul_0-1649275776326.png

 

Rather than having a dedicated VM template with this setting enabled. I was wondering if this is something we could do via cloud template. I am unaware of a way to manage VM Options via vRA blueprints but maybe someone knows a way to do it. 

I do see some PowerCLI post perhaps, a way to use flags.VbsEnabled = $true within the bluprint? 

https://communities.vmware.com/t5/VMware-PowerCLI-Discussions/Turn-on-Virtualization-based-security-...

Thank you! 

0 Kudos
1 Solution

Accepted Solutions
johnbowdre
Enthusiast
Enthusiast

Yep. You'd put a boolean input on the request form, bind it to a customProperty on the resource, and then set a filter on the subscription so that it will only call the vRO workflow if the boolean is true.

So something like this in the Cloud Assembly template:

inputs:
  enableVBS:
    type: boolean
    title: Enable VBS
[...]
resources:
  VM_1:
    type: Cloud.vSphere.Machine
    properties:
      enableVBS: ${input.enableVBS}
      [...]

 

And you could put something like this in the condition filter when creating the subscription:

event.data["customProperties"]["enableVBS"] == "true"

johnbowdre_0-1649769376478.png

 

Alternatively, put a check for that boolean at the top of the script in the vRO workflow:

// Input: inputProperties from vRA
var enableVBS = inputProperties.customProperties.enableVBS
if (enableVBS == "true") { 
  var name = inputProperties.resourceNames[0]
  var vms = VcPlugin.getAllVirtualMachines(null, name)
  vm = vms[0]

  var bootOpts = new VcVirtualMachineBootOptions()
  var flags = new VcVirtualMachineFlagInfo()
  var spec = new VcVirtualMachineConfigSpec()

  bootOpts.efiSecureBootEnabled = true;
  flags.vbsEnabled = true;
  flags.vvtdEnabled = true;

  spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
  spec.nestedHVEnabled = true;
  spec.bootOptions = bootOpts;
  spec.flags = flags;

  vm.reconfigVM_Task(spec)
}

 

View solution in original post

7 Replies
johnbowdre
Enthusiast
Enthusiast

Running that PowerCLI from ABX should work from what I can tell.

Another approach might be to do it with vRO and talk to the vCenter plugin instead of needing to run PowerCLI. I've got some notes on using vRO to change a VM configSpec here. You should be able to take that as a framework and modify the workflow with something like this:

// Input: inputProperties from vRA
var name = inputProperties.resourceNames[0]
var vms = VcPlugin.getAllVirtualMachines(null, name)
vm = vms[0]

var bootOpts = new VcVirtualMachineBootOptions()
var flags = new VcVirtualMachineFlagInfo()
var firmwareType = new VcGuestOsDescriptorFirmwareType()
var spec = new VcVirtualMachineConfigSpec()

bootOpts.efiSecureBootEnabled = true;
flags.vbsEnabled = true;
flags.vvtdEnabled = true;

spec.firmware = firmwareType.efi;
spec.nestedHVEnabled = true;
spec.bootOptions = bootOpts;
spec.flags = flags;

vm.reconfigVM_Task(spec)

 

I've not tested this yet but it seems like it should work - and, if not, it will hopefully at least get you close.

vmsiul
Enthusiast
Enthusiast

Hi John, 

I went ahead with the vRO route, something new so let's try! 

I've followed your blog and did the following:

1.) Create a new workflow "VM Post-Provisioning"

2.) Create  inputProperties of type Properties and outputs, etc as described in your blog. 

3.) Scriptable task Get VM Object

4.) Use the following script for # 3 

 

 

 

 

 

 

 

 

// Javascript: Get VM Object
//    Inputs: inputProperties (Properties)

var name = inputProperties.resourceNames[0]

var vms = VcPlugin.getAllVirtualMachines(null, name)
System.log("Found VM object: " + vms[0])
vm = vms[0]

 

 

 

 

 

 

 

 

5.) Add another scriptable task - Enable VBS 

 

 

 

 

 

 

 

 

// Input: inputProperties from vRA
var name = inputProperties.resourceNames[0]
var vms = VcPlugin.getAllVirtualMachines(null, name)
vm = vms[0]

var bootOpts = new VcVirtualMachineBootOptions()
var flags = new VcVirtualMachineFlagInfo()
var firmwareType = new VcGuestOsDescriptorFirmwareType()
var spec = new VcVirtualMachineConfigSpec()

bootOpts.efiSecureBootEnabled = true;
flags.vbsEnabled = true;
flags.vvtdEnabled = true;

spec.firmware = firmwareType.efi;
spec.nestedHVEnabled = true;
spec.bootOptions = bootOpts;
spec.flags = flags;

vm.reconfigVM_Task(spec)

 

 

 

 

 

 

 

 

6.) Set subscription and link to workflow. 

7.) Add the vCenter Server instance to vRO so that part is done. 

Next I create the VM via Cloud Assembly the VM gets created but when I check the vRO workflow I see the following error in log: 

-------

2022-04-10 17:06:02.362 -04:00INFO__item_stack:/item1
2022-04-10 17:06:02.556 -04:00INFOFound VM object: DynamicWrapper (Instance) : [VcVirtualMachine]-[class com.vmware.o11n.plugin.vsphere_gen.VirtualMachine_Wrapper] -- VALUE : Stub: moRef = (ManagedObjectReference: type = VirtualMachine, value = vm-731293, serverGuid = null), binding = https://vcenter.mydomain.com:443/sdk
2022-04-10 17:06:02.681 -04:00INFO__item_stack:/item2
2022-04-10 17:06:03.667 -04:00ERRORUnable to create object : VcGuestOsDescriptorFirmwareType : com.vmware.vim.binding.vim.vm.GuestOsDescriptor$FirmwareType
2022-04-10 17:06:03.684 -04:00ERRORWorkflow execution stack:
***
item: 'VM-PostProvisioning/item2', state: 'failed', business state: 'null', exception: 'Unable to create object : VcGuestOsDescriptorFirmwareType : com.vmware.vim.binding.vim.vm.GuestOsDescriptor$FirmwareType'
workflow: 'VM-PostProvisioning' (69e17978-0ab6-4ff3-a294-de8339bc8d49)
| 'attribute': name=vm type=VC:VirtualMachine value=dunes://service.dunes.ch/CustomSDKObject?id='vcenter.mydomain.com%2Cid:vm-731293'&dunesName='VC:VirtualMachine'
| 'input': name=inputProperties type=Properties value={9:42:addresses=Array#[31:Array#[20:string#172.4.9.16]]
11:30:componentId=string#Cloud_vSphere_Machine_1

With the above errors I've decided to comment the firmware references in the script and run it again via Cloud Assembly 

 

 

 

 

 

// Input: inputProperties from vRA
var name = inputProperties.resourceNames[0]
var vms = VcPlugin.getAllVirtualMachines(null, name)
vm = vms[0]

var bootOpts = new VcVirtualMachineBootOptions()
var flags = new VcVirtualMachineFlagInfo()
// var firmwareType = new VcGuestOsDescriptorFirmwareType()
var spec = new VcVirtualMachineConfigSpec()

bootOpts.efiSecureBootEnabled = true;
flags.vbsEnabled = true;
flags.vvtdEnabled = true;

//spec.firmware = firmwareType.efi;
spec.nestedHVEnabled = true;
spec.bootOptions = bootOpts;
spec.flags = flags;

vm.reconfigVM_Task(spec)

 

 

 

 

 

 

This time the workflow run was successfully, log shows the following:

 
 
2022-04-10 23:31:52.347 -04:00INFO__item_stack:/item1
2022-04-10 23:31:52.509 -04:00INFOFound VM object: DynamicWrapper (Instance) : [VcVirtualMachine]-[class com.vmware.o11n.plugin.vsphere_gen.VirtualMachine_Wrapper] -- VALUE : Stub: moRef = (ManagedObjectReference: type = VirtualMachine, value = vm-731294, serverGuid = null), binding = https://vcenter.mydomain.com:443/sdk
2022-04-10 23:31:52.714 -04:00INFO__item_stack:/item2
2022-04-10 23:31:53.781 -04:00INFO__item_stack:/item0

-------------------------

Even though the workflow runs successfully once the firmware lines were commented VBS isn't enabled. One thing to note is that VBS can not be enabled while the VM is running. I have connected to vCenter via PowerCLI and ran the script against the VM that Cloud Assembly created and the script works and VBS gets enabled. The same lines that are being executed by vRO are working when I run them from PowerCLI while the VM is powered off. 

I am wondering if there is a way to debug this, maybe the workflow/script is executed while the VM is running, if that's the case then the script will fail, we can only enable VBS when the VM is powered off. I not sure if we could run the workflow directly against the VM to verify that works? 

I have also changed the subscription to computer initial power on but same result, it's runs successfully but VBS is not enabled. 

Thanks again for the help! 🙂 

0 Kudos
johnbowdre
Enthusiast
Enthusiast

You don't really need the "Get VM Object" task since the "Enable VBS" task already has the bit of code up top to extract the VM's name from the inputProperties and use that to obtain the VM object. (Having it won't hurt anything, of course; it's just a bit redundant.) The important part is just to make sure that the script knows which virtual machine the vm variable refers to.

You may want to add the shutdownVM and startVM actions from the preinstalled com.vmware.library.vc.vm.power module to the workflow to stop and start the VM as needed.

And it looks like I made an incorrect assumption about how to reference the firmware type. Just doing spec.firmware = VcGuestOsDescriptorFirmwareType.efi; should do the trick. (I was able to test just that portion and it seems to work.)

 

// Input: inputProperties from vRA
var name = inputProperties.resourceNames[0]
var vms = VcPlugin.getAllVirtualMachines(null, name)
vm = vms[0]

var bootOpts = new VcVirtualMachineBootOptions()
var flags = new VcVirtualMachineFlagInfo()
var spec = new VcVirtualMachineConfigSpec()

bootOpts.efiSecureBootEnabled = true;
flags.vbsEnabled = true;
flags.vvtdEnabled = true;

spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
spec.nestedHVEnabled = true;
spec.bootOptions = bootOpts;
spec.flags = flags;

vm.reconfigVM_Task(spec)

 

vmsiul
Enthusiast
Enthusiast

Hi John - I've reviewed the end to end one more time and I had a typo in the vRO input/output. Once I got that fixed then run the request again from vRA everything worked! 🙂 

...now the last piece of the puzzle! Not every single VM request requires VBS, currently this is happening as part of a subscription (computer initial power on), would be possible to limit this to a user input something like a boolean so when the users checks the option while selection other stuff they will execute the workflow/script when vRA creates the VM request.    

vmsiul_0-1649708083331.png

 

Inputs:
 app11:
    type: boolean
    title: Nested Virtualization
    default: false
resources:
  Cloud_vSphere_Machine_1:
...
  app11:'${input.app1 == true ?  "Something that will trigger the vRO VM workflow 
  that will enable VBS" :  ""}'

 

I am trying to make the above work but no luck so far.... 

Thank you! 

0 Kudos
johnbowdre
Enthusiast
Enthusiast

I think the easiest approach would be to put a filter directly on the subscription in Cloud Assembly. Something like this should do the trick:
https://www.virtual-allan.com/vmware-vra-8-subscriptions-and-advanced-condition-filters/ 

vmsiul
Enthusiast
Enthusiast

Ok, thanks! I apologize I am trying to understand how would the filter will allow the users to say if they want VBS enabled when they request the VM via service Broker? Unfortunately, all the users should be able to request VBS as an option if they need it so we can’t control who does or doesn’t. Could we use a filter that will tie into a Boolean or something similar that will allow the users to make their selection? 

Thanks again! 

0 Kudos
johnbowdre
Enthusiast
Enthusiast

Yep. You'd put a boolean input on the request form, bind it to a customProperty on the resource, and then set a filter on the subscription so that it will only call the vRO workflow if the boolean is true.

So something like this in the Cloud Assembly template:

inputs:
  enableVBS:
    type: boolean
    title: Enable VBS
[...]
resources:
  VM_1:
    type: Cloud.vSphere.Machine
    properties:
      enableVBS: ${input.enableVBS}
      [...]

 

And you could put something like this in the condition filter when creating the subscription:

event.data["customProperties"]["enableVBS"] == "true"

johnbowdre_0-1649769376478.png

 

Alternatively, put a check for that boolean at the top of the script in the vRO workflow:

// Input: inputProperties from vRA
var enableVBS = inputProperties.customProperties.enableVBS
if (enableVBS == "true") { 
  var name = inputProperties.resourceNames[0]
  var vms = VcPlugin.getAllVirtualMachines(null, name)
  vm = vms[0]

  var bootOpts = new VcVirtualMachineBootOptions()
  var flags = new VcVirtualMachineFlagInfo()
  var spec = new VcVirtualMachineConfigSpec()

  bootOpts.efiSecureBootEnabled = true;
  flags.vbsEnabled = true;
  flags.vvtdEnabled = true;

  spec.firmware = VcGuestOsDescriptorFirmwareType.efi;
  spec.nestedHVEnabled = true;
  spec.bootOptions = bootOpts;
  spec.flags = flags;

  vm.reconfigVM_Task(spec)
}