Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TL toggle on vm repair create to allow nested virtualization on repair VMs #7991

Merged
merged 10 commits into from
Oct 16, 2024
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
3 changes: 2 additions & 1 deletion src/vm-repair/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ Release History
===============
1.1.0
++++++
Added script for GT fixit button
Added script for GT fixit button.
Added support for `--disable-trusted-launch` flag parameter to set security type to `Standard` on the repair VM no matter what the source VM has.

1.0.10
++++++
Expand Down
1 change: 1 addition & 0 deletions src/vm-repair/azext_vm_repair/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def load_arguments(self, _):
c.argument('associate_public_ip', help='Option to create repair vm with public ip')
c.argument('distro', help='Option to create repair vm from a specific linux distro (rhel7|rhel8|sles12|sles15|ubuntu20|centos7|centos8|oracle7)')
c.argument('yes', help='Option to skip prompt for associating public ip and confirm yes to it in no Tty mode')
c.argument('disable_trusted_launch', help='Option to disable Trusted Launch security type on the repair vm by setting the security type to Standard.')

with self.argument_context('vm repair restore') as c:
c.argument('repair_vm_id', help='Repair VM resource id.')
Expand Down
35 changes: 21 additions & 14 deletions src/vm-repair/azext_vm_repair/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@
logger = get_logger(__name__)


def create(cmd, vm_name, resource_group_name, repair_password=None, repair_username=None, repair_vm_name=None, copy_disk_name=None, repair_group_name=None, unlock_encrypted_vm=False, enable_nested=False, associate_public_ip=False, distro='ubuntu', yes=False, encrypt_recovery_key=""):
def create(cmd, vm_name, resource_group_name, repair_password=None, repair_username=None, repair_vm_name=None, copy_disk_name=None, repair_group_name=None, unlock_encrypted_vm=False, enable_nested=False, associate_public_ip=False, distro='ubuntu', yes=False, encrypt_recovery_key="", disable_trusted_launch=False):
# Breaking change warning
logger.warning('After the November 2024 release, if the image of the source Windows VM is not found, the \'az vm repair create\' command will default to use a 2022-Datacenter image for the repair VM.')

# log all the parameters not logging the bitlocker key
logger.debug('vm repair create command parameters: vm_name: %s, resource_group_name: %s, repair_password: %s, repair_username: %s, repair_vm_name: %s, copy_disk_name: %s, repair_group_name: %s, unlock_encrypted_vm: %s, enable_nested: %s, associate_public_ip: %s, distro: %s, yes: %s', vm_name, resource_group_name, repair_password, repair_username, repair_vm_name, copy_disk_name, repair_group_name, unlock_encrypted_vm, enable_nested, associate_public_ip, distro, yes)
logger.debug('vm repair create command parameters: vm_name: %s, resource_group_name: %s, repair_password: %s, repair_username: %s, repair_vm_name: %s, copy_disk_name: %s, repair_group_name: %s, unlock_encrypted_vm: %s, enable_nested: %s, associate_public_ip: %s, distro: %s, yes: %s, disable_trusted_launch: %s', vm_name, resource_group_name, repair_password, repair_username, repair_vm_name, copy_disk_name, repair_group_name, unlock_encrypted_vm, enable_nested, associate_public_ip, distro, yes, disable_trusted_launch)

# Init command helper object
command = command_helper(logger, cmd, 'vm repair create')
Expand Down Expand Up @@ -118,17 +117,25 @@ def create(cmd, vm_name, resource_group_name, repair_password=None, repair_usern
zone = source_vm.zones[0]
create_repair_vm_command += ' --zone {zone}'.format(zone=zone)

if encrypt_recovery_key:
# For confidential VM and Trusted VM security tags some of the SKU expects the right security type, secure_boot_enabled and vtpm_enabled
logger.debug('Fetching VM security profile...')
vm_security_params = _fetch_vm_security_profile_parameters(source_vm)
if vm_security_params:
create_repair_vm_command += vm_security_params

logger.debug('Fetching OS Disk security profile...')
osdisk_security_params = _fetch_osdisk_security_profile_parameters(source_vm)
if osdisk_security_params:
create_repair_vm_command += osdisk_security_params
if disable_trusted_launch:
logger.debug('Set security-type to Standard...')
create_repair_vm_command += ' --security-type Standard'
else:
# For confidential VM and Trusted VM security tags some of the SKU expects the right security type, secure_boot_enabled and vtpm_enabled

# Note: I don't think TL VMs have an envrypted disk, so I don't think they need the encrypt_recovery_key parameter. Needs to be investigated and reworked.
# TL VMs still have a security profile to copy over though.
if encrypt_recovery_key:
logger.debug('Fetching VM security profile...')
vm_security_params = _fetch_vm_security_profile_parameters(source_vm)
if vm_security_params:
create_repair_vm_command += vm_security_params
# For confidential VM and Trusted Launch VM security tags on disks, the disk security profile needs to be brought over as well.
if encrypt_recovery_key:
logger.debug('Fetching OS Disk security profile...')
osdisk_security_params = _fetch_osdisk_security_profile_parameters(source_vm)
if osdisk_security_params:
create_repair_vm_command += osdisk_security_params

# Create new resource group
existing_rg = _check_existing_rg(repair_group_name)
Expand Down
5 changes: 3 additions & 2 deletions src/vm-repair/azext_vm_repair/repair_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ def _unlock_singlepass_encrypted_disk(repair_vm_name, repair_group_name, is_linu

def _unlock_singlepass_encrypted_disk_fallback(source_vm, resource_group_name, repair_vm_name, repair_group_name, copy_disk_name, is_linux):
"""
This method is not actually invoked.
Fallback for unlocking disk when script fails. This will install the ADE extension to unlock the Data disk.
"""

Expand Down Expand Up @@ -507,13 +508,13 @@ def _fetch_compatible_windows_os_urn_v2(source_vm):
offer = source_vm.storage_profile.image_reference.offer
publisher = source_vm.storage_profile.image_reference.publisher
fetch_urn_command = 'az vm image list -s {sku} -f {offer} -p {publisher} -l {loc} --verbose --all --query "[?sku==\'{sku}\'].urn | reverse(sort(@))" -o json'.format(loc=location, sku=sku, offer=offer, publisher=publisher)
logger.info('Fetching compatible Windows OS images from gallery...')
logger.info('Fetching compatible Windows OS images from gallery V2...')
urns = loads(_call_az_command(fetch_urn_command))

if not urns or len(urns) == 0:
# If source SKU not available then defaulting 2022 datacenter image.
fetch_urn_command = 'az vm image list -s "2022-Datacenter" -f WindowsServer -p MicrosoftWindowsServer -l {loc} --verbose --all --query "[?sku==\'2022-datacenter\'].urn | reverse(sort(@))" -o json'.format(loc=location)
logger.info('Fetching compatible Windows OS images from gallery for 2022 Datacenter...')
logger.info('Fetching compatible Windows OS images from gallery for 2022 Datacenter V2...')
urns = loads(_call_az_command(fetch_urn_command))

# No OS images available for Windows2016
Expand Down
41 changes: 41 additions & 0 deletions src/vm-repair/azext_vm_repair/tests/latest/test_repair_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,47 @@ def test_vmrepair_ConfidentialVMAndUnlockDisk(self, resource_group):
# Call Restore
self.cmd('vm repair restore -g {rg} -n {vm} --yes')

# Check swapped OS disk
vms = self.cmd('vm list -g {rg} -o json').get_output_in_json()
source_vm = vms[0]
assert source_vm['storageProfile']['osDisk']['name'] == result['copied_disk_name']


@pytest.mark.winTrustedLaunchVMFlag
class WindowsTrustedLaunchVMFlag(LiveScenarioTest):

@ResourceGroupPreparer(location='westus2')
def test_vmrepair_TrustedLaunchVMFlag(self, resource_group):
self.kwargs.update({
'vm': 'vm1',
'rg': resource_group
})

# Create test VM
# need to create a TL VM
self.cmd('vm create -g {rg} -n {vm} --admin-username azureadmin --admin-password !Passw0rd2024 --image Win2022Datacenter')
vms = self.cmd('vm list -g {rg} -o json').get_output_in_json()
# Something wrong with vm create command if it fails here
assert len(vms) == 1

# Test create
result = self.cmd('vm repair create -g {rg} -n {vm} --repair-username azureadmin --repair-password !Passw0rd2024 --yes --unlock-encrypted-vm --encrypt-recovery-key !Passw0rd2024 --disable-trusted-launch --verbose -o json').get_output_in_json()
assert result['status'] == STATUS_SUCCESS, result['error_message']

# Check repair VM
repair_vms = self.cmd('vm list -g {} -o json'.format(result['repair_resource_group'])).get_output_in_json()
assert len(repair_vms) == 1
repair_vm = repair_vms[0]
print("Printing repair VM Output")
print(repair_vm)
security_profile_repair_vm = repair_vm.get("securityProfile")
assert security_profile_repair_vm is None
# Check attached data disk
assert repair_vm['storageProfile']['dataDisks'][0]['name'] == result['copied_disk_name']

# Call Restore
self.cmd('vm repair restore -g {rg} -n {vm} --yes')

# Check swapped OS disk
vms = self.cmd('vm list -g {rg} -o json').get_output_in_json()
source_vm = vms[0]
Expand Down
2 changes: 0 additions & 2 deletions src/vm-repair/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
from codecs import open
from setuptools import setup, find_packages


VERSION = "1.1.0"


CLASSIFIERS = [
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
Expand Down
Loading