Skip to content
Merged
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
10 changes: 10 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,10 @@ def load_arguments(self, _):
help="enable/disable disk write accelerator. Use singular value 'true/false' to apply across, or specify individual disks, e.g.'os=true 1=true 2=true' for os disk and data disks with lun of 1 & 2")
c.argument('disk_caching', nargs='*', help="Use singular value to apply across, or specify individual disks, e.g. 'os=ReadWrite 0=None 1=ReadOnly' should enable update os disk and 2 data disks")
c.argument('ultra_ssd_enabled', ultra_ssd_enabled_type)
c.argument('enable_secure_boot', arg_type=get_three_state_flag(), min_api='2020-12-01',
help='Enable secure boot.')
c.argument('enable_vtpm', arg_type=get_three_state_flag(), min_api='2020-12-01',
help='Enable vTPM.')

with self.argument_context('vm create') as c:
c.argument('name', name_arg_type, validator=_resource_not_exists(self.cli_ctx, 'Microsoft.Compute/virtualMachines'))
Expand Down Expand Up @@ -349,6 +353,12 @@ def load_arguments(self, _):
help='Specify the scale set logical fault domain into which the virtual machine will be created. By default, the virtual machine will be automatically assigned to a fault domain that best maintains balance across available fault domains. This is applicable only if the virtualMachineScaleSet property of this virtual machine is set. The virtual machine scale set that is referenced, must have platform fault domain count. This property cannot be updated once the virtual machine is created. Fault domain assignment can be viewed in the virtual machine instance view')
c.argument('count', type=int, is_preview=True,
help='Number of virtual machines to create. Value range is [2, 250], inclusive. Don\'t specify this parameter if you want to create a normal single VM. The VMs are created in parallel. The output of this command is an array of VMs instead of one single VM. Each VM has its own public IP, NIC. VNET and NSG are shared. It is recommended that no existing public IP, NIC, VNET and NSG are in resource group. When --count is specified, --attach-data-disks, --attach-os-disk, --boot-diagnostics-storage, --computer-name, --host, --host-group, --nics, --os-disk-name, --private-ip-address, --public-ip-address, --public-ip-address-dns-name, --storage-account, --storage-container-name, --subnet, --use-unmanaged-disk, --vnet-name are not allowed.')
c.argument('security_type', arg_type=get_enum_type(['TrustedLaunch']), min_api='2020-12-01',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, is there any relationship among the 3 params?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.microsoft.com/en-us/azure/virtual-machines/trusted-launch
Secure boot and vTPM are features of trusted launch.

help='Specify if the VM is Trusted Launch enabled. See https://docs.microsoft.com/azure/virtual-machines/trusted-launch.')
c.argument('enable_secure_boot', arg_type=get_three_state_flag(), min_api='2020-12-01',
help='Enable secure boot. It is part of trusted launch.')
c.argument('enable_vtpm', arg_type=get_three_state_flag(), min_api='2020-12-01',
help='Enable vTPM. It is part of trusted launch.')

with self.argument_context('vm create', arg_group='Storage') as c:
c.argument('attach_os_disk', help='Attach an existing OS disk to the VM. Can use the name or ID of a managed disk or the URI to an unmanaged disk VHD.')
Expand Down
16 changes: 14 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/_template_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ def build_vm_resource( # pylint: disable=too-many-locals, too-many-statements
computer_name=None, dedicated_host=None, priority=None, max_price=None, eviction_policy=None,
enable_agent=None, vmss=None, os_disk_encryption_set=None, data_disk_encryption_sets=None, specialized=None,
encryption_at_host=None, dedicated_host_group=None, enable_auto_update=None, patch_mode=None,
enable_hotpatching=None, platform_fault_domain=None, count=None):
enable_hotpatching=None, platform_fault_domain=None, security_type=None, enable_secure_boot=None,
enable_vtpm=None, count=None):

os_caching = disk_info['os'].get('caching')

Expand Down Expand Up @@ -501,8 +502,19 @@ def _build_storage_profile():
if max_price is not None:
vm_properties['billingProfile'] = {'maxPrice': max_price}

vm_properties['securityProfile'] = {}

if encryption_at_host is not None:
vm_properties['securityProfile'] = {'encryptionAtHost': encryption_at_host}
vm_properties['securityProfile']['encryptionAtHost'] = encryption_at_host

if security_type is not None:
vm_properties['securityProfile']['securityType'] = security_type

if enable_secure_boot is not None or enable_vtpm is not None:
vm_properties['securityProfile']['uefiSettings'] = {
'secureBootEnabled': enable_secure_boot,
'vTpmEnabled': enable_vtpm
}

if platform_fault_domain is not None:
vm_properties['platformFaultDomain'] = platform_fault_domain
Expand Down
15 changes: 12 additions & 3 deletions src/azure-cli/azure/cli/command_modules/vm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,8 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
priority=None, max_price=None, eviction_policy=None, enable_agent=None, workspace=None, vmss=None,
os_disk_encryption_set=None, data_disk_encryption_sets=None, specialized=None,
encryption_at_host=None, enable_auto_update=None, patch_mode=None, ssh_key_name=None,
enable_hotpatching=None, platform_fault_domain=None, count=None):
enable_hotpatching=None, platform_fault_domain=None, security_type=None, enable_secure_boot=None,
enable_vtpm=None, count=None):
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.util import random_string, hash_string
from azure.cli.core.commands.arm import ArmTemplateBuilder
Expand Down Expand Up @@ -915,7 +916,8 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
data_disk_encryption_sets=data_disk_encryption_sets, specialized=specialized,
encryption_at_host=encryption_at_host, dedicated_host_group=dedicated_host_group,
enable_auto_update=enable_auto_update, patch_mode=patch_mode, enable_hotpatching=enable_hotpatching,
platform_fault_domain=platform_fault_domain, count=count)
platform_fault_domain=platform_fault_domain, security_type=security_type, enable_secure_boot=enable_secure_boot,
enable_vtpm=enable_vtpm, count=count)

vm_resource['dependsOn'] = vm_dependencies

Expand Down Expand Up @@ -1313,7 +1315,8 @@ def show_vm(cmd, resource_group_name, vm_name, show_details=False):

def update_vm(cmd, resource_group_name, vm_name, os_disk=None, disk_caching=None,
write_accelerator=None, license_type=None, no_wait=False, ultra_ssd_enabled=None,
priority=None, max_price=None, proximity_placement_group=None, workspace=None, **kwargs):
priority=None, max_price=None, proximity_placement_group=None, workspace=None, enable_secure_boot=None,
enable_vtpm=None, **kwargs):
from msrestazure.tools import parse_resource_id, resource_id, is_valid_resource_id
from ._vm_utils import update_write_accelerator_settings, update_disk_caching
vm = kwargs['parameters']
Expand Down Expand Up @@ -1357,6 +1360,12 @@ def update_vm(cmd, resource_group_name, vm_name, os_disk=None, disk_caching=None
if proximity_placement_group is not None:
vm.proximity_placement_group = {'id': proximity_placement_group}

if enable_secure_boot is not None or enable_vtpm is not None:
vm.security_profile = {'uefiSettings': {
'secureBootEnabled': enable_secure_boot,
'vTpmEnabled': enable_vtpm
}}

if workspace is not None:
workspace_id = _prepare_workspace(cmd, resource_group_name, workspace)
workspace_name = parse_resource_id(workspace_id)['name']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5072,6 +5072,29 @@ def test_vm_ssh_key(self, resource_group):
self.cmd('sshkey show -g {rg} -n k3')


class VMTrustedLaunchScenarioTest(ScenarioTest):
@unittest.skip('Not supported')
@ResourceGroupPreparer(name_prefix='cli_test_vm_trusted_launch_', location='southcentralus')
def test_vm_trusted_launch(self, resource_group):
self.cmd('vm create -g {rg} -n vm --image Win2019Datacenter --security-type TrustedLaunch --enable-secure-boot true --enable-vtpm true --admin-username azureuser --admin-password testPassword0 --nsg-rule None')
self.cmd('vm show -g {rg} -n vm', checks=[
self.check('securityProfile.securityType', 'TrustedLaunch'),
self.check('securityProfile.UefiSettings.secureBootEnabled', True),
self.check('securityProfile.UefiSettings.vTpmEnabled', True)
])

@unittest.skip('Not supported')
@ResourceGroupPreparer(name_prefix='cli_test_vm_trusted_launch_update_', location='southcentralus')
def test_vm_trusted_launch_update(self, resource_group):
self.cmd('vm create -g {rg} -n vm --image Win2019Datacenter --security-type TrustedLaunch --admin-username azureuser --admin-password testPassword0 --nsg-rule None')
self.cmd('vm update -g {rg} -n vm --enable-secure-boot true --enable-vtpm true')
self.cmd('vm show -g {rg} -n vm', checks=[
self.check('securityProfile.securityType', 'TrustedLaunch'),
self.check('securityProfile.UefiSettings.secureBootEnabled', True),
self.check('securityProfile.UefiSettings.vTpmEnabled', True)
])


class VMCreateCountScenarioTest(ScenarioTest):
@ResourceGroupPreparer(name_prefix='cli_test_vm_create_count_')
def test_vm_create_count(self, resource_group):
Expand Down