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

[Compute] az vm/vmss create: Install guest attestation extension and turn on system MSI by default when Trusted Launch configuration is met #22048

Merged
merged 18 commits into from
Apr 22, 2022
Merged
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 (installing guest attestation extension and turning on MSI) when creating VM/VMSS compliant with Trusted Launch.')
zhoxing-ms marked this conversation as resolved.
Show resolved Hide resolved

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
13 changes: 13 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,19 @@ 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]')

# Enable system assigned msi by default when Trusted Launch configuration is met
if hasattr(namespace, 'disable_integrity_monitoring') and not namespace.disable_integrity_monitoring:
if hasattr(namespace, 'security_type') and hasattr(namespace, 'enable_vtpm') \
and hasattr(namespace, 'enable_secure_boot'):
if namespace.security_type and namespace.security_type.lower() == 'trustedlaunch' and\
namespace.enable_vtpm and namespace.enable_secure_boot:
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
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
64 changes: 62 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,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 @@ -1073,6 +1073,34 @@ 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
if security_type and security_type.lower() == 'trustedlaunch' and enable_vtpm and\
enable_secure_boot and not disable_integrity_monitoring:
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
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)
guest_attestation_extension = LongRunningOperation(cmd.cli_ctx)(
client.virtual_machine_extensions.begin_create_or_update(resource_group_name,
vm_name,
'GuestAttestation',
ext))
if guest_attestation_extension.provisioning_state == 'Succeeded':
logger.info('Guest Attestation Extension has been successfully installed by default')
else:
logger.error('Failed to install Guest Attestation Extension by default')
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
if count:
vm_names = [vm_name + str(i) for i in range(count)]
else:
Expand Down Expand Up @@ -2846,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 @@ -3178,6 +3206,38 @@ 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
if security_type and security_type.lower() == 'trustedlaunch' and enable_vtpm and\
enable_secure_boot and not disable_integrity_monitoring:
Jing-song marked this conversation as resolved.
Show resolved Hide resolved
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)
guest_attestation_extension = LongRunningOperation(cmd.cli_ctx)(
client.virtual_machine_scale_sets.begin_create_or_update(resource_group_name, vmss_name, vmss))
if guest_attestation_extension.provisioning_state == 'Succeeded':
logger.info('Guest Attestation Extension has been successfully installed by default')
else:
logger.error('Failed to install Guest Attestation Extension by default')
Jing-song marked this conversation as resolved.
Show resolved Hide resolved

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