Skip to content

Commit

Permalink
[Compute] az vm/vmss create: Install guest attestation extension an…
Browse files Browse the repository at this point in the history
…d turn on system MSI by default when Trusted Launch configuration is met (Azure#22048)
  • Loading branch information
Jing-song authored Apr 22, 2022
1 parent ce055fd commit a0057a0
Show file tree
Hide file tree
Showing 7 changed files with 16,204 additions and 114 deletions.
1 change: 1 addition & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,7 @@ def load_arguments(self, _):
c.ignore('aux_subscriptions')
c.argument('edge_zone', edge_zone_type)
c.argument('accept_term', action='store_true', help="Accept the license agreement and privacy statement.")
c.argument('disable_integrity_monitoring', action='store_true', min_api='2020-12-01', help='Disable the default behavior of installing guest attestation extension and enabling System Assigned Identity for Trusted Launch enabled VMs and VMSS.')

with self.argument_context(scope, arg_group='Authentication') as c:
c.argument('generate_ssh_keys', action='store_true', help='Generate SSH public and private key files if missing. The keys will be stored in the ~/.ssh directory')
Expand Down
16 changes: 16 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,22 @@ def _validate_vm_vmss_msi(cmd, namespace, is_identity_assign=False):
elif namespace.identity_scope or namespace.identity_role:
raise ArgumentUsageError('usage error: --assign-identity [--scope SCOPE] [--role ROLE]')

if not is_identity_assign:
_enable_msi_for_trusted_launch(namespace)


def _enable_msi_for_trusted_launch(namespace):
# Enable system assigned msi by default when Trusted Launch configuration is met
is_trusted_launch = namespace.security_type and namespace.security_type.lower() == 'trustedlaunch' \
and namespace.enable_vtpm and namespace.enable_secure_boot
if is_trusted_launch and not namespace.disable_integrity_monitoring:
from ._vm_utils import MSI_LOCAL_ID
logger.info('The MSI is enabled by default when Trusted Launch configuration is met')
if namespace.assign_identity is None:
namespace.assign_identity = [MSI_LOCAL_ID]
elif '[system]' not in namespace.assign_identity:
namespace.assign_identity.append(MSI_LOCAL_ID)


def _validate_vm_vmss_set_applications(cmd, namespace): # pylint: disable=unused-argument
if namespace.application_configuration_overrides and \
Expand Down
67 changes: 64 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 @@ -764,7 +764,7 @@ def capture_vm(cmd, resource_group_name, vm_name, vhd_name_prefix,
print(json.dumps(output, indent=2)) # pylint: disable=no-member


# pylint: disable=too-many-locals, unused-argument, too-many-statements, too-many-branches
# pylint: disable=too-many-locals, unused-argument, too-many-statements, too-many-branches, broad-except
def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_v2', location=None, tags=None,
no_wait=False, authentication_type=None, admin_password=None, computer_name=None,
admin_username=None, ssh_dest_key_path=None, ssh_key_value=None, generate_ssh_keys=False,
Expand All @@ -789,7 +789,7 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
enable_hotpatching=None, platform_fault_domain=None, security_type=None, enable_secure_boot=None,
enable_vtpm=None, count=None, edge_zone=None, nic_delete_option=None, os_disk_delete_option=None,
data_disk_delete_option=None, user_data=None, capacity_reservation_group=None, enable_hibernation=None,
v_cpus_available=None, v_cpus_per_core=None, accept_term=None):
v_cpus_available=None, v_cpus_per_core=None, accept_term=None, disable_integrity_monitoring=False):

from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.util import random_string, hash_string
Expand Down Expand Up @@ -1074,6 +1074,33 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
return sdk_no_wait(no_wait, client.begin_create_or_update, resource_group_name, deployment_name, deployment)
LongRunningOperation(cmd.cli_ctx)(client.begin_create_or_update(resource_group_name, deployment_name, deployment))

# Guest Attestation Extension and enable System Assigned MSI by default
is_trusted_launch = security_type and security_type.lower() == 'trustedlaunch' and\
enable_vtpm and enable_secure_boot
if is_trusted_launch and not disable_integrity_monitoring:
vm = get_vm(cmd, resource_group_name, vm_name, 'instanceView')
client = _compute_client_factory(cmd.cli_ctx)
if vm.storage_profile.os_disk.os_type == 'Linux':
publisher = 'Microsoft.Azure.Security.LinuxAttestation'
if vm.storage_profile.os_disk.os_type == 'Windows':
publisher = 'Microsoft.Azure.Security.WindowsAttestation'
version = _normalize_extension_version(cmd.cli_ctx, publisher, 'GuestAttestation', None, vm.location)
VirtualMachineExtension = cmd.get_models('VirtualMachineExtension')
ext = VirtualMachineExtension(location=vm.location,
publisher=publisher,
type_properties_type='GuestAttestation',
protected_settings=None,
type_handler_version=version,
settings=None,
auto_upgrade_minor_version=True,
enable_automatic_upgrade=None)
try:
LongRunningOperation(cmd.cli_ctx)(client.virtual_machine_extensions.begin_create_or_update(
resource_group_name, vm_name, 'GuestAttestation', ext))
logger.info('Guest Attestation Extension has been successfully installed by default '
'when Trusted Launch configuration is met')
except Exception as e:
logger.error('Failed to install Guest Attestation Extension for Trusted Launch. %s', e)
if count:
vm_names = [vm_name + str(i) for i in range(count)]
else:
Expand Down Expand Up @@ -2847,7 +2874,7 @@ def create_vmss(cmd, vmss_name, resource_group_name, image=None,
user_data=None, network_api_version=None, enable_spot_restore=None, spot_restore_timeout=None,
capacity_reservation_group=None, enable_auto_update=None, patch_mode=None, enable_agent=None,
security_type=None, enable_secure_boot=None, enable_vtpm=None, automatic_repairs_action=None,
v_cpus_available=None, v_cpus_per_core=None, accept_term=None):
v_cpus_available=None, v_cpus_per_core=None, accept_term=None, disable_integrity_monitoring=False):

from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.util import random_string, hash_string
Expand Down Expand Up @@ -3179,6 +3206,40 @@ def _get_public_ip_address_allocation(value, sku):
deployment_result['vmss']['identity'] = _construct_identity_info(identity_scope, identity_role,
vmss_info.identity.principal_id,
vmss_info.identity.user_assigned_identities)
# Guest Attestation Extension and enable System Assigned MSI by default
is_trusted_launch = security_type and security_type.lower() == 'trustedlaunch' and\
enable_vtpm and enable_secure_boot
if is_trusted_launch and not disable_integrity_monitoring:
client = _compute_client_factory(cmd.cli_ctx)
vmss = client.virtual_machine_scale_sets.get(resource_group_name, vmss_name)
vmss.virtual_machine_profile.storage_profile.image_reference = None
VirtualMachineScaleSetExtension, VirtualMachineScaleSetExtensionProfile = cmd.get_models(
'VirtualMachineScaleSetExtension', 'VirtualMachineScaleSetExtensionProfile')
if vmss.virtual_machine_profile.storage_profile.os_disk.os_type == 'Linux':
publisher = 'Microsoft.Azure.Security.LinuxAttestation'
if vmss.virtual_machine_profile.storage_profile.os_disk.os_type == 'Windows':
publisher = 'Microsoft.Azure.Security.WindowsAttestation'
version = _normalize_extension_version(cmd.cli_ctx, publisher, 'GuestAttestation', None, vmss.location)
ext = VirtualMachineScaleSetExtension(name='GuestAttestation',
publisher=publisher,
type_properties_type='GuestAttestation',
protected_settings=None,
type_handler_version=version,
settings=None,
auto_upgrade_minor_version=True,
provision_after_extensions=None,
enable_automatic_upgrade=None)
if not vmss.virtual_machine_profile.extension_profile:
vmss.virtual_machine_profile.extension_profile = VirtualMachineScaleSetExtensionProfile(extensions=[])
vmss.virtual_machine_profile.extension_profile.extensions.append(ext)
try:
LongRunningOperation(cmd.cli_ctx)(client.virtual_machine_scale_sets.begin_create_or_update(
resource_group_name, vmss_name, vmss))
logger.info('Guest Attestation Extension has been successfully installed by default'
'when Trusted Launch configuration is met')
except Exception as e:
logger.error('Failed to install Guest Attestation Extension for Trusted Launch. %s', e)

return deployment_result


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ vmss create:
prioritize_unhealthy_instances:
rule_exclusions:
- option_length_too_long
disable_integrity_monitoring:
rule_exclusions:
- option_length_too_long
vmss update:
parameters:
enable_cross_zone_upgrade:
Expand Down Expand Up @@ -57,6 +60,9 @@ vm create:
public_ip_address_allocation:
rule_exclusions:
- missing_parameter_help
disable_integrity_monitoring:
rule_exclusions:
- option_length_too_long
vm unmanaged-disk attach:
parameters:
size_gb:
Expand Down
Loading

0 comments on commit a0057a0

Please sign in to comment.