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] Support trusted launch for disk #23026

Merged
merged 20 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
482ec78
disk support uploading with security data
zhoxing-ms Jun 24, 2022
5aca528
Add min api-version control
zhoxing-ms Jun 27, 2022
9fad3c4
Modify original verification
zhoxing-ms Jun 27, 2022
82a21d3
Hide the --secure-vm-guest-state-sas parameter and add more informati…
zhoxing-ms Jun 28, 2022
0832cfe
Hide the --secure-vm-guest-state-sas parameter and add more informati…
zhoxing-ms Jun 28, 2022
f950e7a
Fix grant access data bug
zhoxing-ms Jun 28, 2022
fc6ed25
test secure upload
Jing-song Jun 29, 2022
7c83910
disk support uploading with security data
zhoxing-ms Jun 30, 2022
3e9e911
Fix the create option
zhoxing-ms Jun 30, 2022
444d711
Merge branch 'disk_support_trust_launch' of https://github.com/zhoxin…
Jing-song Jun 30, 2022
043c7b1
Add verification for security_data_uri
zhoxing-ms Jun 30, 2022
ce73b94
Merge branch 'disk_support_trust_launch' of github.com:zhoxing-ms/azu…
zhoxing-ms Jun 30, 2022
d332393
Expose secure_vm_guest_state_sas
zhoxing-ms Jun 30, 2022
48ad61f
test --secure-vm-guest-state-sas and upload type
Jing-song Jun 30, 2022
6220b5c
Add configuration in CredScanSuppression
zhoxing-ms Jun 30, 2022
b0143e1
validation test
Jing-song Jun 30, 2022
d8bf54f
Fix CI issue
zhoxing-ms Jun 30, 2022
13135fc
Merge branch 'disk_support_trust_launch' of github.com:zhoxing-ms/azu…
zhoxing-ms Jun 30, 2022
bb0025a
Merge branch 'dev' of github.com:Azure/azure-cli into disk_support_tr…
zhoxing-ms Jun 30, 2022
94cb3f6
validation test
Jing-song Jun 30, 2022
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
6 changes: 6 additions & 0 deletions scripts/ci/credscan/CredScanSuppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,12 @@
"src\\azure-cli\\azure\\cli\\command_modules\\container\\tests\\latest\\recordings\\test_container_create_with_acr.yaml"
],
"_justification": "[Container] one-off password used in test, not persisted"
},
{
"file": [
"src\\azure-cli\\azure\\cli\\command_modules\\vm\\tests\\latest\\recordings\\test_vm_trusted_launch_os_disk_secure_upload.yaml"
],
"_justification": "[VM] the SAS tokens come from the temporary test resources"
}
]
}
12 changes: 12 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@
- name: Create a disk and associate it with a disk access resource.
text: >
az disk create -g MyResourceGroup -n MyDisk --size-gb 10 --network-access-policy AllowPrivate --disk-access MyDiskAccessID
- name: Create a disk from the blob URI for VM guest state VHD.
text: >
az disk create -g MyResourceGroup -n MyDisk --size-gb 10 --security-data-uri GuestStateDiskVhdUri --security-type TrustedLaunch --hyper-v-generation V2
- name: Create a standard disk for uploading blobs.
text: >
az disk create -g MyResourceGroup -n MyDisk --size-gb 10 --upload-type Upload
- name: Create an OS disk for uploading along with VM guest state.
text: >
az disk create -g MyResourceGroup -n MyDisk --size-gb 10 --upload-type UploadWithSecurityData --security-type TrustedLaunch --hyper-v-generation V2
"""

helps['disk delete'] = """
Expand All @@ -100,6 +109,9 @@
text: |
az disk grant-access --access-level Read --duration-in-seconds 3600 --name MyManagedDisk --resource-group MyResourceGroup
crafted: true
- name: Grant a resource read access to a disk to generate access SAS and security data access SAS
text: |
az disk grant-access --access-level Read --duration-in-seconds 3600 --name MyDisk --resource-group MyResourceGroup --secure-vm-guest-state-sas
"""

helps['disk list'] = """
Expand Down
23 changes: 20 additions & 3 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from azure.cli.command_modules.vm._validators import (
validate_nsg_name, validate_vm_nics, validate_vm_nic, validate_vmss_disk,
validate_asg_names_or_ids, validate_keyvault, _validate_proximity_placement_group,
validate_vm_name_for_monitor_metrics)
validate_vm_name_for_monitor_metrics, validate_secure_vm_guest_state_sas)

from azure.cli.command_modules.vm._vm_utils import MSI_LOCAL_ID
from azure.cli.command_modules.vm._image_builder import ScriptType
Expand Down Expand Up @@ -147,8 +147,6 @@ def load_arguments(self, _):
c.argument('duration_in_seconds', help='Time duration in seconds until the SAS access expires', type=int)
if self.supported_api_version(min_api='2018-09-30', operation_group='disks'):
c.argument('access_level', arg_type=get_enum_type(['Read', 'Write']), default='Read', help='access level')
c.argument('for_upload', arg_type=get_three_state_flag(),
help='Create the {0} for uploading blobs later on through storage commands. Run "az {0} grant-access --access-level Write" to retrieve the {0}\'s SAS token.'.format(scope))
c.argument('hyper_v_generation', arg_type=hyper_v_gen_sku, help='The hypervisor generation of the Virtual Machine. Applicable to OS disks only.')
else:
c.ignore('access_level', 'for_upload', 'hyper_v_generation')
Expand All @@ -169,6 +167,13 @@ def load_arguments(self, _):
c.argument('secure_vm_disk_encryption_set', min_api='2021-08-01', help='Name or ID of disk encryption set created with ConfidentialVmEncryptedWithCustomerKey encryption type.')
# endregion

# region Disks
with self.argument_context('disk grant-access', resource_type=ResourceType.MGMT_COMPUTE, operation_group='disks') as c:
c.argument('secure_vm_guest_state_sas', options_list=['--secure-vm-guest-state-sas', '-s'], min_api='2022-03-02',
action='store_true', validator=validate_secure_vm_guest_state_sas,
help="Get SAS on managed disk with VM guest state. It will be used by default when the create option of disk is 'secureOSUpload'")
# endregion

# region Disks
with self.argument_context('disk', resource_type=ResourceType.MGMT_COMPUTE, operation_group='disks') as c:
c.argument('zone', zone_type, min_api='2017-03-30', options_list=['--zone']) # TODO: --size-gb currently has claimed -z. We can do a breaking change later if we want to.
Expand Down Expand Up @@ -197,6 +202,16 @@ def load_arguments(self, _):
c.argument('data_access_auth_mode', arg_type=get_enum_type(['AzureActiveDirectory', 'None']), min_api='2021-12-01', help='Specify the auth mode when exporting or uploading to a disk or snapshot.')
# endregion

# region Disks
with self.argument_context('disk create', resource_type=ResourceType.MGMT_COMPUTE, operation_group='disks') as c:
c.argument('security_data_uri', min_api='2022-03-02', help='Please specify the blob URI of VHD to be imported into VM guest state')
c.argument('for_upload', arg_type=get_three_state_flag(), min_api='2018-09-30',
deprecate_info=c.deprecate(target='--for-upload', redirect='--upload-type Upload', hide=True),
help='Create the disk for uploading blobs. Replaced by "--upload-type Upload"')
c.argument('upload_type', arg_type=get_enum_type(['Upload', 'UploadWithSecurityData']), min_api='2018-09-30',
help="Create the disk for upload scenario. 'Upload' is for Standard disk only upload. 'UploadWithSecurityData' is for OS Disk upload along with VM Guest State. Please note the 'UploadWithSecurityData' is not valid for data disk upload, it only to be used for OS Disk upload at present.")
# endregion

# region Snapshots
with self.argument_context('snapshot', resource_type=ResourceType.MGMT_COMPUTE, operation_group='snapshots') as c:
c.argument('snapshot_name', existing_snapshot_name, id_part='name', completer=get_resource_name_completion_list('Microsoft.Compute/snapshots'))
Expand All @@ -208,6 +223,8 @@ def load_arguments(self, _):
c.argument('copy_start', arg_type=get_three_state_flag(), min_api='2021-04-01',
help='Create snapshot by using a deep copy process, where the resource creation is considered complete only after all data has been copied from the source.')
c.argument('architecture', arg_type=get_enum_type(self.get_models('Architecture', operation_group='snapshots')), min_api='2021-12-01', help='CPU architecture.')
c.argument('for_upload', arg_type=get_three_state_flag(), min_api='2018-09-30',
help='Create the snapshot for uploading blobs later on through storage commands. Run "az snapshot grant-access --access-level Write" to retrieve the snapshot\'s SAS token.')
# endregion

# region Images
Expand Down
51 changes: 51 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 @@ -1766,6 +1766,8 @@ def process_disk_create_namespace(cmd, namespace):
validate_tags(namespace)
validate_edge_zone(cmd, namespace)
_validate_gallery_image_reference(cmd, namespace)
_validate_security_data_uri(namespace)
_validate_upload_type(cmd, namespace)
_validate_secure_vm_disk_encryption_set(namespace)
_validate_hyper_v_generation(namespace)
if namespace.source:
Expand All @@ -1781,6 +1783,46 @@ def process_disk_create_namespace(cmd, namespace):
raise ArgumentUsageError(usage_error)


def _validate_security_data_uri(namespace):
if 'security_data_uri' not in namespace or not namespace.security_data_uri:
return

if not namespace.security_type:
raise RequiredArgumentMissingError(
'Please specify --security-type when using the --security-data-uri parameter')

if not namespace.hyper_v_generation or namespace.hyper_v_generation != 'V2':
raise ArgumentUsageError(
"Please specify --hyper-v-generation as 'V2' when using the --security-data-uri parameter")

if not namespace.source:
raise RequiredArgumentMissingError(
'Please specify --source when using the --security-data-uri parameter')


def _validate_upload_type(cmd, namespace):
if 'upload_type' not in namespace:
return

if not namespace.upload_type and namespace.for_upload:
namespace.upload_type = 'Upload'

if namespace.upload_type == 'UploadWithSecurityData':

if not cmd.supported_api_version(min_api='2021-08-01', operation_group='disks'):
raise ArgumentUsageError(
"'UploadWithSecurityData' is not supported in the current profile. "
"Please upgrade your profile with 'az cloud set --profile newerProfile' and try again")

if not namespace.security_type:
raise RequiredArgumentMissingError(
"Please specify --security-type when the value of --upload-type is 'UploadWithSecurityData'")

if not namespace.hyper_v_generation or namespace.hyper_v_generation != 'V2':
raise ArgumentUsageError(
"Please specify --hyper-v-generation as 'V2' the value of --upload-type is 'UploadWithSecurityData'")


def _validate_secure_vm_disk_encryption_set(namespace):
if 'secure_vm_disk_encryption_set' not in namespace:
return
Expand Down Expand Up @@ -2303,3 +2345,12 @@ def _validate_community_gallery_legal_agreement_acceptance(cmd, namespace):
if not prompt_y_n(msg, default="y"):
import sys
sys.exit(0)


def validate_secure_vm_guest_state_sas(cmd, namespace):
compute_client = _compute_client_factory(cmd.cli_ctx)
disk_info = compute_client.disks.get(namespace.resource_group_name, namespace.disk_name)
DiskCreateOption = cmd.get_models('DiskCreateOption')

if disk_info.creation_data and disk_info.creation_data.create_option == DiskCreateOption.upload_prepared_secure:
namespace.secure_vm_guest_state_sas = True
46 changes: 32 additions & 14 deletions src/azure-cli/azure/cli/command_modules/vm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,16 @@ def _get_sku_object(cmd, sku):
return sku


def _grant_access(cmd, resource_group_name, name, duration_in_seconds, is_disk, access_level):
def _grant_access(cmd, resource_group_name, name, duration_in_seconds, is_disk, access_level,
secure_vm_guest_state_sas=None):
AccessLevel, GrantAccessData = cmd.get_models('AccessLevel', 'GrantAccessData')
client = _compute_client_factory(cmd.cli_ctx)
op = client.disks if is_disk else client.snapshots
grant_access_data = GrantAccessData(
access=access_level or AccessLevel.read, duration_in_seconds=duration_in_seconds)
grant_access_data = GrantAccessData(access=access_level or AccessLevel.read,
duration_in_seconds=duration_in_seconds)
if secure_vm_guest_state_sas:
grant_access_data.get_secure_vm_guest_state_sas = secure_vm_guest_state_sas

return op.begin_grant_access(resource_group_name, name, grant_access_data)


Expand Down Expand Up @@ -297,23 +301,28 @@ def create_managed_disk(cmd, resource_group_name, disk_name, location=None, # p
network_access_policy=None, disk_access=None, logical_sector_size=None,
tier=None, enable_bursting=None, edge_zone=None, security_type=None, support_hibernation=None,
public_network_access=None, accelerated_network=None, architecture=None,
data_access_auth_mode=None, gallery_image_reference_type=None,
secure_vm_disk_encryption_set=None):
data_access_auth_mode=None, gallery_image_reference_type=None, security_data_uri=None,
upload_type=None, secure_vm_disk_encryption_set=None):

from msrestazure.tools import resource_id, is_valid_resource_id
from azure.cli.core.commands.client_factory import get_subscription_id

Disk, CreationData, DiskCreateOption, Encryption = cmd.get_models(
'Disk', 'CreationData', 'DiskCreateOption', 'Encryption')

location = location or _get_resource_group_location(cmd.cli_ctx, resource_group_name)
if source_blob_uri:
if security_data_uri:
option = DiskCreateOption.import_secure
elif source_blob_uri:
option = DiskCreateOption.import_enum
elif source_disk or source_snapshot:
option = DiskCreateOption.copy
elif source_restore_point:
option = DiskCreateOption.restore
elif for_upload:
elif upload_type == 'Upload':
option = DiskCreateOption.upload
elif upload_type == 'UploadWithSecurityData':
option = DiskCreateOption.upload_prepared_secure
elif image_reference or gallery_image_reference:
option = DiskCreateOption.from_image
else:
Expand All @@ -326,8 +335,9 @@ def create_managed_disk(cmd, resource_group_name, disk_name, location=None, # p
subscription=subscription_id, resource_group=resource_group_name,
namespace='Microsoft.Storage', type='storageAccounts', name=storage_account_name)

if upload_size_bytes is not None and for_upload is not True:
raise CLIError('usage error: --upload-size-bytes should be used together with --for-upload')
if upload_size_bytes is not None and not upload_type:
raise RequiredArgumentMissingError(
'usage error: --upload-size-bytes should be used together with --upload-type')

if image_reference is not None:
if not is_valid_resource_id(image_reference):
Expand Down Expand Up @@ -360,10 +370,16 @@ def create_managed_disk(cmd, resource_group_name, disk_name, location=None, # p
source_resource_id=source_disk or source_snapshot or source_restore_point,
storage_account_id=source_storage_account_id,
upload_size_bytes=upload_size_bytes,
logical_sector_size=logical_sector_size)
logical_sector_size=logical_sector_size,
security_data_uri=security_data_uri)

if size_gb is None and upload_size_bytes is None and (option == DiskCreateOption.empty or for_upload):
raise CLIError('usage error: --size-gb or --upload-size-bytes required to create an empty disk')
if size_gb is None and upload_size_bytes is None:
if option == DiskCreateOption.empty:
raise RequiredArgumentMissingError(
'usage error: --size-gb or --upload-size-bytes required to create an empty disk')
if upload_type:
raise RequiredArgumentMissingError(
'usage error: --size-gb or --upload-size-bytes required to create a disk for upload')

if disk_encryption_set is not None and not is_valid_resource_id(disk_encryption_set):
disk_encryption_set = resource_id(
Expand Down Expand Up @@ -435,9 +451,11 @@ def create_managed_disk(cmd, resource_group_name, disk_name, location=None, # p
return sdk_no_wait(no_wait, client.disks.begin_create_or_update, resource_group_name, disk_name, disk)


def grant_disk_access(cmd, resource_group_name, disk_name, duration_in_seconds, access_level=None):
def grant_disk_access(cmd, resource_group_name, disk_name, duration_in_seconds, access_level=None,
secure_vm_guest_state_sas=None):

return _grant_access(cmd, resource_group_name, disk_name, duration_in_seconds, is_disk=True,
access_level=access_level)
access_level=access_level, secure_vm_guest_state_sas=secure_vm_guest_state_sas)


def list_managed_disks(cmd, resource_group_name=None):
Expand Down
Loading