def process_nw_test_connectivity_namespace(namespace): from azure.cli.core.commands.arm import parse_resource_id compute_client = get_mgmt_service_client(ResourceType.MGMT_COMPUTE).virtual_machines vm_name = parse_resource_id(namespace.source_resource)['name'] rg = namespace.resource_group_name or parse_resource_id(namespace.source_resource).get('resource_group', None) if not rg: raise CLIError('usage error: --source-resource ID | --source-resource NAME --resource-group NAME') vm = compute_client.get(rg, vm_name) namespace.location = vm.location # pylint: disable=no-member get_network_watcher_from_location(remove=True)(namespace) if namespace.source_resource and not is_valid_resource_id(namespace.source_resource): namespace.source_resource = resource_id( subscription=get_subscription_id(), resource_group=rg, namespace='Microsoft.Compute', type='virtualMachines', name=namespace.source_resource) if namespace.dest_resource and not is_valid_resource_id(namespace.dest_resource): namespace.dest_resource = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group_name, namespace='Microsoft.Compute', type='virtualMachines', name=namespace.dest_resource)
def _verify_keyvault_good_for_encryption(disk_vault_id, kek_vault_id, vmss, force): def _report_client_side_validation_error(msg): if force: logger.warning(msg) else: raise CLIError(msg) from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.mgmt.keyvault import KeyVaultManagementClient client = get_mgmt_service_client(KeyVaultManagementClient).vaults disk_vault_resource_info = parse_resource_id(disk_vault_id) key_vault = client.get(disk_vault_resource_info['resource_group'], disk_vault_resource_info['name']) # ensure vault has 'EnabledForDiskEncryption' permission if not key_vault.properties.enabled_for_disk_encryption: _report_client_side_validation_error("keyvault '{}' is not enabled for disk encryption. ".format( disk_vault_resource_info['resource_name'])) if kek_vault_id: kek_vault_info = parse_resource_id(kek_vault_id) if disk_vault_resource_info['name'].lower() != kek_vault_info['name'].lower(): client.get(kek_vault_info['resource_group'], kek_vault_info['name']) # verify subscription mataches vmss_resource_info = parse_resource_id(vmss.id) if vmss_resource_info['subscription'].lower() != disk_vault_resource_info['subscription'].lower(): _report_client_side_validation_error( "VM scale set's subscription doesn't match keyvault's subscription. Encryption might fail") # verify region matches if key_vault.location.replace(' ', '').lower() != vmss.location.replace(' ', '').lower(): _report_client_side_validation_error( "VM scale set's region doesn't match keyvault's region. Encryption might fail")
def _validate_vm_create_storage_account(namespace): if namespace.storage_account: storage_id = parse_resource_id(namespace.storage_account) rg = storage_id.get('resource_group', namespace.resource_group_name) if check_existence(storage_id['name'], rg, 'Microsoft.Storage', 'storageAccounts'): # 1 - existing storage account specified namespace.storage_account_type = 'existing' logger.debug("using specified existing storage account '%s'", storage_id['name']) else: # 2 - params for new storage account specified namespace.storage_account_type = 'new' logger.debug("specified storage account '%s' not found and will be created", storage_id['name']) else: from azure.cli.core.profiles import ResourceType from azure.cli.core.commands.client_factory import get_mgmt_service_client storage_client = get_mgmt_service_client(ResourceType.MGMT_STORAGE).storage_accounts # find storage account in target resource group that matches the VM's location sku_tier = 'Premium' if 'Premium' in namespace.storage_sku else 'Standard' account = next( (a for a in storage_client.list_by_resource_group(namespace.resource_group_name) if a.sku.tier.value == sku_tier and a.location == namespace.location), None) if account: # 3 - nothing specified - find viable storage account in target resource group namespace.storage_account = account.name namespace.storage_account_type = 'existing' logger.debug("suitable existing storage account '%s' will be used", account.name) else: # 4 - nothing specified - create a new storage account namespace.storage_account_type = 'new' logger.debug('no suitable storage account found. One will be created.')
def build_msi_role_assignment(vm_vmss_name, vm_vmss_resource_id, role_definition_id, role_assignment_guid, identity_scope, is_vm=True): from azure.cli.core.commands.arm import parse_resource_id from azure.mgmt.authorization import AuthorizationManagementClient from azure.cli.core.commands.client_factory import get_mgmt_service_client result = parse_resource_id(identity_scope) if result.get('type'): # is a resource id? name = '{}/Microsoft.Authorization/{}'.format(result['name'], role_assignment_guid) assignment_type = '{}/{}/providers/roleAssignments'.format(result['namespace'], result['type']) else: name = role_assignment_guid assignment_type = 'Microsoft.Authorization/roleAssignments' # pylint: disable=line-too-long msi_rp_api_version = '2015-08-31-PREVIEW' authorization_api_version = get_mgmt_service_client(AuthorizationManagementClient).api_version return { 'name': name, 'type': assignment_type, 'apiVersion': authorization_api_version, 'dependsOn': [ 'Microsoft.Compute/{}/{}'.format('virtualMachines' if is_vm else 'virtualMachineScaleSets', vm_vmss_name) ], 'properties': { 'roleDefinitionId': role_definition_id, 'principalId': "[reference('{}/providers/Microsoft.ManagedIdentity/Identities/default', '{}').principalId]".format( vm_vmss_resource_id, msi_rp_api_version), 'scope': identity_scope } }
def validate_client_parameters(namespace): """ Retrieves storage connection parameters from environment variables and parses out connection string into account name and key """ n = namespace if not n.connection_string: n.connection_string = az_config.get('storage', 'connection_string', None) # if connection string supplied or in environment variables, extract account key and name if n.connection_string: conn_dict = validate_key_value_pairs(n.connection_string) n.account_name = conn_dict['AccountName'] n.account_key = conn_dict['AccountKey'] # otherwise, simply try to retrieve the remaining variables from environment variables if not n.account_name: n.account_name = az_config.get('storage', 'account', None) if not n.account_key: n.account_key = az_config.get('storage', 'key', None) if not n.sas_token: n.sas_token = az_config.get('storage', 'sas_token', None) # if account name is specified but no key, attempt to query if n.account_name and not n.account_key: scf = get_mgmt_service_client(StorageManagementClient) acc = next((x for x in scf.storage_accounts.list() if x.name == n.account_name), None) if acc: from azure.cli.core.commands.arm import parse_resource_id rg = parse_resource_id(acc.id)['resource_group'] n.account_key = \ scf.storage_accounts.list_keys(rg, n.account_name).keys[0].value # pylint: disable=no-member else: raise ValueError("Storage account '{}' not found.".format(n.account_name))
def list_policy_assignment(show_all=False, include_inherited=False, resource_group_name=None, resource_id=None): policy_client = _resource_policy_client_factory() if show_all: if resource_group_name or resource_id: raise CLIError('group or resource id are not required when --show-all is used') scope = _build_policy_scope(policy_client.config.subscription_id, resource_group_name, resource_id) if resource_group_name: result = policy_client.policy_assignments.list_for_resource_group(resource_group_name) elif resource_id: #pylint: disable=redefined-builtin id = parse_resource_id(resource_id) parent_resource_path = None if not id['child_name'] else (id['type'] + '/' + id['name']) resource_type = id['child_type'] or id['type'] resource_name = id['child_name'] or id['name'] result = policy_client.policy_assignments.list_for_resource( id['resource_group'], id['namespace'], parent_resource_path, resource_type, resource_name) else: result = policy_client.policy_assignments.list() if show_all: return result if not include_inherited: result = [i for i in result if scope.lower() == i.scope.lower()] return result
def process_image_create_namespace(namespace): try: # try capturing from VM, a most common scenario compute_client = _compute_client_factory() res_id = _get_resource_id(namespace.source, namespace.resource_group_name, 'virtualMachines', 'Microsoft.Compute') res = parse_resource_id(res_id) vm_info = compute_client.virtual_machines.get(res['resource_group'], res['name']) # pylint: disable=no-member namespace.os_type = vm_info.storage_profile.os_disk.os_type.value namespace.source_virtual_machine = res_id if namespace.data_disk_sources: raise CLIError("'--data-disk-sources' is not allowed when capturing " "images from virtual machines") except CloudError: namespace.os_blob_uri, namespace.os_disk, namespace.os_snapshot = _figure_out_storage_source(namespace.resource_group_name, namespace.source) # pylint: disable=line-too-long namespace.data_blob_uris = [] namespace.data_disks = [] namespace.data_snapshots = [] if namespace.data_disk_sources: for data_disk_source in namespace.data_disk_sources: source_blob_uri, source_disk, source_snapshot = _figure_out_storage_source( namespace.resource_group_name, data_disk_source) if source_blob_uri: namespace.data_blob_uris.append(source_blob_uri) if source_disk: namespace.data_disks.append(source_disk) if source_snapshot: namespace.data_snapshots.append(source_snapshot) if not namespace.os_type: raise CLIError("usage error: os type is required to create the image, " "please specify '--os-type OS_TYPE'")
def move_resource(ids, destination_group, destination_subscription_id=None): '''Moves resources from one resource group to another(can be under different subscription) :param ids: the space separated resource ids to be moved :param destination_group: the destination resource group name :param destination_subscription_id: the destination subscription identifier ''' from azure.cli.core.commands.arm import resource_id #verify all resource ids are valid and under the same group resources = [] for i in ids: if is_valid_resource_id(i): resources.append(parse_resource_id(i)) else: raise CLIError('Invalid id "{}", as it has no group or subscription field'.format(i)) if len(set([r['subscription'] for r in resources])) > 1: raise CLIError('All resources should be under the same subscription') if len(set([r['resource_group'] for r in resources])) > 1: raise CLIError('All resources should be under the same group') rcf = _resource_client_factory() target = resource_id(subscription=(destination_subscription_id or rcf.config.subscription_id), resource_group=destination_group) return rcf.resources.move_resources(resources[0]['resource_group'], ids, target)
def check_existence(value, resource_group, provider_namespace, resource_type, parent_name=None, parent_type=None): # check for name or ID and set the type flags from azure.mgmt.resource.resources import ResourceManagementClient from azure.cli.core.commands.client_factory import get_mgmt_service_client from msrestazure.azure_exceptions import CloudError resource_client = get_mgmt_service_client(ResourceManagementClient).resources id_parts = parse_resource_id(value) rg = id_parts.get("resource_group", resource_group) ns = id_parts.get("namespace", provider_namespace) if parent_name and parent_type: parent_path = "{}/{}".format(parent_type, parent_name) resource_name = id_parts.get("child_name", value) resource_type = id_parts.get("child_type", resource_type) else: parent_path = "" resource_name = id_parts["name"] resource_type = id_parts.get("type", resource_type) api_version = _resolve_api_version(provider_namespace, resource_type, parent_path) try: resource_client.get(rg, ns, parent_path, resource_type, resource_name, api_version) return True except CloudError: return False
def create_resource(self, properties, location, is_full_object): res = json.loads(properties) if not is_full_object: if not location: if self.resource_id: rg_name = parse_resource_id(self.resource_id)['resource_group'] else: rg_name = self.resource_group_name location = self.rcf.resource_groups.get(rg_name).location res = GenericResource(location=location, properties=res) elif res.get('location', None) is None: raise IncorrectUsageError("location of the resource is required") if self.resource_id: resource = self.rcf.resources.create_or_update_by_id(self.resource_id, self.api_version, res) else: resource = self.rcf.resources.create_or_update(self.resource_group_name, self.resource_provider_namespace, self.parent_resource_path or '', self.resource_type, self.resource_name, self.api_version, res) return resource
def create_webapp(resource_group, name, plan): client = web_client_factory() if is_valid_resource_id(plan): plan = parse_resource_id(plan)['name'] location = _get_location_from_app_service_plan(client, resource_group, plan) webapp_def = Site(server_farm_id=plan, location=location) return client.sites.create_or_update_site(resource_group, name, webapp_def)
def _validate_vm_create_storage_account(namespace): if namespace.storage_account: storage_id = parse_resource_id(namespace.storage_account) rg = storage_id.get('resource_group', namespace.resource_group_name) if check_existence(storage_id['name'], rg, 'Microsoft.Storage', 'storageAccounts'): # 1 - existing storage account specified namespace.storage_account_type = 'existing' else: # 2 - params for new storage account specified namespace.storage_account_type = 'new' else: from azure.mgmt.storage import StorageManagementClient from azure.cli.core.commands.client_factory import get_mgmt_service_client storage_client = get_mgmt_service_client(StorageManagementClient).storage_accounts # find storage account in target resource group that matches the VM's location sku_tier = 'Premium' if 'Premium' in namespace.storage_sku else 'Standard' account = next( (a for a in storage_client.list_by_resource_group(namespace.resource_group_name) if a.sku.tier.value == sku_tier and a.location == namespace.location), None) if account: # 3 - nothing specified - find viable storage account in target resource group namespace.storage_account = account.name namespace.storage_account_type = 'existing' else: # 4 - nothing specified - create a new storage account namespace.storage_account_type = 'new'
def list_policy_assignment(disable_scope_strict_match=None, resource_group_name=None, scope=None): policy_client = _resource_policy_client_factory() if scope and not is_valid_resource_id(scope): parts = scope.strip('/').split('/') if len(parts) == 4: resource_group_name = parts[3] elif len(parts) == 2: #rarely used, but still verify if parts[1].lower() != policy_client.config.subscription_id.lower(): raise CLIError("Please use current active subscription's id") else: err = "Invalid scope '{}', it should point to a resource group or a resource" raise CLIError(err.format(scope)) scope = None _scope = _build_policy_scope(policy_client.config.subscription_id, resource_group_name, scope) if resource_group_name: result = policy_client.policy_assignments.list_for_resource_group(resource_group_name) elif scope: #pylint: disable=redefined-builtin id = parse_resource_id(scope) parent_resource_path = '' if not id.get('child_name') else (id['type'] + '/' + id['name']) resource_type = id.get('child_type') or id['type'] resource_name = id.get('child_name') or id['name'] result = policy_client.policy_assignments.list_for_resource( id['resource_group'], id['namespace'], parent_resource_path, resource_type, resource_name) else: result = policy_client.policy_assignments.list() if not disable_scope_strict_match: result = [i for i in result if _scope.lower() == i.scope.lower()] return result
def _validate_name_or_id( resource_group_name, property_value, property_type, parent_value, parent_type): from azure.cli.core.commands.client_factory import get_subscription_id has_parent = parent_type is not None if is_valid_resource_id(property_value): resource_id_parts = parse_resource_id(property_value) value_supplied_was_id = True elif has_parent: resource_id_parts = dict( name=parent_value, resource_group=resource_group_name, namespace=parent_type.split('/')[0], type=parent_type.split('/')[1], subscription=get_subscription_id(), child_name=property_value, child_type=property_type) value_supplied_was_id = False else: resource_id_parts = dict( name=property_value, resource_group=resource_group_name, namespace=property_type.split('/')[0], type=property_type.split('/')[1], subscription=get_subscription_id()) value_supplied_was_id = False return (resource_id_parts, value_supplied_was_id)
def get_network_watcher_from_vm(namespace): from azure.cli.core.commands.arm import parse_resource_id compute_client = get_mgmt_service_client(ResourceType.MGMT_COMPUTE).virtual_machines vm_name = parse_resource_id(namespace.vm)['name'] vm = compute_client.get(namespace.resource_group_name, vm_name) namespace.location = vm.location # pylint: disable=no-member get_network_watcher_from_location()(namespace)
def create_webapp(resource_group_name, name, plan): client = web_client_factory() if is_valid_resource_id(plan): plan = parse_resource_id(plan)['name'] location = _get_location_from_app_service_plan(client, resource_group_name, plan) webapp_def = Site(server_farm_id=plan, location=location) poller = client.web_apps.create_or_update(resource_group_name, name, webapp_def) return AppServiceLongRunningOperation()(poller)
def list_slots(resource_group_name, webapp): client = web_client_factory() slots = list(client.web_apps.list_slots(resource_group_name, webapp)) for slot in slots: slot.name = slot.name.split('/')[-1] setattr(slot, 'app_service_plan', parse_resource_id(slot.server_farm_id)['name']) del slot.server_farm_id return slots
def _validate_lock_params_match_lock( # pylint: disable=too-many-arguments lock_client, name, resource_group_name, resource_provider_namespace, parent_resource_path, resource_type, resource_name): """ Locks are scoped to subscription, resource group or resource. However, the az list command returns all locks for the current scopes and all lower scopes (e.g. resource group level also includes resource locks). This can lead to a confusing user experience where the user specifies a lock name and assumes that it will work, even if they haven't given the right scope. This function attempts to validate the parameters and help the user find the right scope, by first finding the lock, and then infering what it's parameters should be. """ locks = lock_client.management_locks.list_at_subscription_level() found_count = 0 # locks at different levels can have the same name lock_resource_id = None for lock in locks: if lock.name == name: found_count = found_count + 1 lock_resource_id = lock.id if found_count == 1: # If we only found one lock, let's validate that the parameters are correct, # if we found more than one, we'll assume the user knows what they're doing # TODO: Add validation for that case too? resource = parse_resource_id(lock_resource_id) _resource_group = resource.get('resource_group', None) _resource_namespace = resource.get('namespace', None) if _resource_group is None: return if resource_group_name != _resource_group: raise CLIError( 'Unexpected --resource-group for lock {}, expected {}'.format( name, _resource_group)) if _resource_namespace is None: return if resource_provider_namespace != _resource_namespace: raise CLIError( 'Unexpected --namespace for lock {}, expected {}'.format( name, _resource_namespace)) if resource.get('grandchild_type', None) is None: _resource_type = resource.get('type', None) _resource_name = resource.get('name', None) else: _resource_type = resource.get('child_type', None) _resource_name = resource.get('child_name', None) parent = (resource['type'] + '/' + resource['name']) if parent != parent_resource_path: raise CLIError( 'Unexpected --parent for lock {}, expected {}'.format( name, parent)) if resource_type != _resource_type: raise CLIError( 'Unexpected --resource-type for lock {}, expected {}'.format( name, _resource_type)) if resource_name != _resource_name: raise CLIError( 'Unexpected --resource-name for lock {}, expected {}'.format( name, _resource_name))
def create_webapp(resource_group_name, name, plan): client = web_client_factory() if is_valid_resource_id(plan): plan = parse_resource_id(plan)['name'] location = _get_location_from_app_service_plan(client, resource_group_name, plan) webapp_def = Site(server_farm_id=plan, location=location) return client.web_apps.create_or_update(resource_group_name, name, webapp_def)
def list_slots(resource_group_name, webapp): client = web_client_factory() slots = client.web_apps.list_slots(resource_group_name, webapp) for slot in slots: slot.name = slot.name.split('/')[-1] setattr(slot, 'app_service_plan', parse_resource_id(slot.server_farm_id)['name']) del slot.server_farm_id return slots
def _get_resource_name_and_rg(resource_group_name, name_or_id): if is_valid_resource_id(name_or_id): id_parts = parse_resource_id(name_or_id) name = id_parts['name'] resource_group = id_parts['resource_group'] else: name = name_or_id resource_group = resource_group_name return name, resource_group
def _query_account_key(account_name): scf = get_mgmt_service_client(StorageManagementClient) acc = next((x for x in scf.storage_accounts.list() if x.name == account_name), None) if acc: from azure.cli.core.commands.arm import parse_resource_id rg = parse_resource_id(acc.id)['resource_group'] return scf.storage_accounts.list_keys(rg, account_name).keys[0].value # pylint: disable=no-member else: raise ValueError("Storage account '{}' not found.".format(account_name))
def get_network_watcher_from_vm(namespace): from azure.cli.core.commands.arm import parse_resource_id compute_client = get_mgmt_service_client( ResourceType.MGMT_COMPUTE).virtual_machines vm_name = parse_resource_id(namespace.vm)['name'] vm = compute_client.get(namespace.resource_group_name, vm_name) namespace.location = vm.location # pylint: disable=no-member get_network_watcher_from_location()(namespace)
def create_webapp(resource_group_name, name, plan): client = web_client_factory() if is_valid_resource_id(plan): plan = parse_resource_id(plan)['name'] location = _get_location_from_app_service_plan(client, resource_group_name, plan) webapp_def = Site(server_farm_id=plan, location=location) poller = client.sites.create_or_update_site(resource_group_name, name, webapp_def) return AppServiceLongRunningOperation()(poller)
def _validate_lock_params_match_lock( lock_client, name, resource_group_name, resource_provider_namespace, parent_resource_path, resource_type, resource_name): """ Locks are scoped to subscription, resource group or resource. However, the az list command returns all locks for the current scopes and all lower scopes (e.g. resource group level also includes resource locks). This can lead to a confusing user experience where the user specifies a lock name and assumes that it will work, even if they haven't given the right scope. This function attempts to validate the parameters and help the user find the right scope, by first finding the lock, and then infering what it's parameters should be. """ locks = lock_client.management_locks.list_at_subscription_level() found_count = 0 # locks at different levels can have the same name lock_resource_id = None for lock in locks: if lock.name == name: found_count = found_count + 1 lock_resource_id = lock.id if found_count == 1: # If we only found one lock, let's validate that the parameters are correct, # if we found more than one, we'll assume the user knows what they're doing # TODO: Add validation for that case too? resource = parse_resource_id(lock_resource_id) _resource_group = resource.get('resource_group', None) _resource_namespace = resource.get('namespace', None) if _resource_group is None: return if resource_group_name != _resource_group: raise CLIError( 'Unexpected --resource-group for lock {}, expected {}'.format( name, _resource_group)) if _resource_namespace is None: return if resource_provider_namespace != _resource_namespace: raise CLIError( 'Unexpected --namespace for lock {}, expected {}'.format(name, _resource_namespace)) if resource.get('grandchild_type', None) is None: _resource_type = resource.get('type', None) _resource_name = resource.get('name', None) else: _resource_type = resource.get('child_type', None) _resource_name = resource.get('child_name', None) parent = (resource['type'] + '/' + resource['name']) if parent != parent_resource_path: raise CLIError( 'Unexpected --parent for lock {}, expected {}'.format( name, parent)) if resource_type != _resource_type: raise CLIError('Unexpected --resource-type for lock {}, expected {}'.format( name, _resource_type)) if resource_name != _resource_name: raise CLIError('Unexpected --resource-name for lock {}, expected {}'.format( name, _resource_name))
def handle_folding(namespace): base_name_val = getattr(namespace, base_name) type_field_val = getattr(namespace, type_field) parent_name_val = getattr(namespace, parent_name) if parent_name else None if base_name_val is None or type_field_val is not None: # Either no name was specified, or the user specified the type of resource # (i.e. new/existing/none) pass elif base_name_val in ('', '""', "''"): # An empty name specified - that means that we are neither referencing an existing # field, or the name is set to an empty string. We check for all types of quotes # so scripts can run cross-platform. if not none_flag_value: raise CLIError('Field {} cannot be none.'.format( make_camel_case(base_name))) setattr(namespace, type_field, none_flag_value) setattr(namespace, base_name, None) else: from azure.cli.core.commands.client_factory import get_subscription_id has_parent = parent_name is not None and parent_type is not None if is_valid_resource_id(base_name_val): resource_id_parts = parse_resource_id(base_name_val) elif has_parent: resource_id_parts = dict( name=parent_name_val, resource_group=namespace.resource_group_name, namespace=parent_type.split('/')[0], type=parent_type.split('/')[1], subscription=get_subscription_id(), child_name=base_name_val, child_type=resource_type) else: resource_id_parts = dict( name=base_name_val, resource_group=namespace.resource_group_name, namespace=resource_type.split('/')[0], type=resource_type.split('/')[1], subscription=get_subscription_id()) if resource_exists(**resource_id_parts): setattr(namespace, type_field, existing_id_flag_value) setattr(namespace, base_name, resource_id(**resource_id_parts)) elif is_valid_resource_id(base_name_val): raise CLIError('ID {} does not exist. Please specify ' 'a name to create a new resource.'.format( resource_id(**resource_id_parts))) elif not new_flag_value: raise CLIError( 'Referenced resource {} does not exist. Please create the required ' 'resource and try again.'.format( resource_id(**resource_id_parts))) else: setattr(namespace, type_field, new_flag_value)
def validate_diagnostic_settings(namespace): from azure.cli.core.commands.client_factory import get_subscription_id resource_group_error = "--resource-group is required when name is provided for "\ "storage account or workspace or service bus namespace and rule. " if namespace.namespace or namespace.rule_name: if namespace.namespace is None: raise CLIError(resource_group_error) if namespace.rule_name is None: raise CLIError(resource_group_error) if namespace.resource_group is None: raise CLIError(resource_group_error) if not is_valid_resource_id(namespace.namespace): namespace.service_bus_rule_id = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.ServiceBus', type='namespaces', name=namespace.namespace, child_type='AuthorizationRules', child_name=namespace.rule_name) else: resource_dict = parse_resource_id(namespace.namespace) namespace.service_bus_rule_id = resource_id( subscription=resource_dict['subscription'], resource_group=resource_dict['resource_group'], namespace=resource_dict['namespace'], type=resource_dict['type'], name=resource_dict['name'], child_type='AuthorizationRules', child_name=namespace.rule_name) if namespace.storage_account and not is_valid_resource_id( namespace.storage_account): if namespace.resource_group is None: raise CLIError(resource_group_error) namespace.storage_account = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.Storage', type='storageAccounts', name=namespace.storage_account) if namespace.workspace and not is_valid_resource_id(namespace.workspace): if namespace.resource_group is None: raise CLIError(resource_group_error) namespace.workspace = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.OperationalInsights', type='workspaces', name=namespace.workspace) _validate_tags(namespace)
def _verify_keyvault_good_for_encryption(disk_vault_id, kek_vault_id, vmss, force): def _report_client_side_validation_error(msg): if force: logger.warning(msg) else: raise CLIError(msg) from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.mgmt.keyvault import KeyVaultManagementClient client = get_mgmt_service_client(KeyVaultManagementClient).vaults disk_vault_resource_info = parse_resource_id(disk_vault_id) key_vault = client.get(disk_vault_resource_info['resource_group'], disk_vault_resource_info['name']) # ensure vault has 'EnabledForDiskEncryption' permission if not key_vault.properties.enabled_for_disk_encryption: _report_client_side_validation_error( "keyvault '{}' is not enabled for disk encryption. ".format( disk_vault_resource_info['resource_name'])) if kek_vault_id: kek_vault_info = parse_resource_id(kek_vault_id) if disk_vault_resource_info['name'].lower( ) != kek_vault_info['name'].lower(): client.get(kek_vault_info['resource_group'], kek_vault_info['name']) # verify subscription mataches vmss_resource_info = parse_resource_id(vmss.id) if vmss_resource_info['subscription'].lower( ) != disk_vault_resource_info['subscription'].lower(): _report_client_side_validation_error( "VM scale set's subscription doesn't match keyvault's subscription. Encryption might fail" ) # verify region matches if key_vault.location.replace(' ', '').lower() != vmss.location.replace( ' ', '').lower(): _report_client_side_validation_error( "VM scale set's region doesn't match keyvault's region. Encryption might fail" )
def handle_folding(namespace): base_name_val = getattr(namespace, base_name) type_field_val = getattr(namespace, type_field) parent_name_val = getattr(namespace, parent_name) if parent_name else None if base_name_val is None or type_field_val is not None: # Either no name was specified, or the user specified the type of resource # (i.e. new/existing/none) pass elif base_name_val in ('', '""', "''"): # An empty name specified - that means that we are neither referencing an existing # field, or the name is set to an empty string. We check for all types of quotes # so scripts can run cross-platform. if not none_flag_value: raise CLIError('Field {} cannot be none.'.format(make_camel_case(base_name))) setattr(namespace, type_field, none_flag_value) setattr(namespace, base_name, None) else: from azure.cli.core.commands.client_factory import get_subscription_id has_parent = parent_name is not None and parent_type is not None if is_valid_resource_id(base_name_val): resource_id_parts = parse_resource_id(base_name_val) elif has_parent: if not parent_name_val and base_required: raise CLIError("Must specify '{}' when specifying '{}' name.".format( parent_option_flag or parent_name, base_name)) resource_id_parts = dict( name=parent_name_val, resource_group=namespace.resource_group_name, namespace=parent_type.split('/')[0], type=parent_type.split('/')[1], subscription=get_subscription_id(), child_name=base_name_val, child_type=resource_type) else: resource_id_parts = dict( name=base_name_val, resource_group=namespace.resource_group_name, namespace=resource_type.split('/')[0], type=resource_type.split('/')[1], subscription=get_subscription_id()) if resource_exists(**resource_id_parts): setattr(namespace, type_field, existing_id_flag_value) setattr(namespace, base_name, resource_id(**resource_id_parts)) elif is_valid_resource_id(base_name_val): raise CLIError('ID {} does not exist. Please specify ' 'a name to create a new resource.'.format( resource_id(**resource_id_parts))) elif not new_flag_value: raise CLIError('Referenced resource {} does not exist. Please create the required ' 'resource and try again.'.format(resource_id(**resource_id_parts))) else: setattr(namespace, type_field, new_flag_value)
def validate_resource_group_name(ns): if not ns.resource_group_name: vault_name = ns.vault_name client = get_mgmt_service_client(KeyVaultManagementClient).vaults for vault in client.list(): id_comps = parse_resource_id(vault.id) if id_comps['name'] == vault_name: ns.resource_group_name = id_comps['resource_group'] return raise CLIError( "The Resource 'Microsoft.KeyVault/vaults/{}'".format(vault_name) + \ " not found within subscription")
def _get_resource_group_from_vault_name(vault_name): """ Fetch resource group from vault name :param str vault_name: name of the key vault :return: resource group name or None :rtype: str """ client = get_mgmt_service_client(KeyVaultManagementClient).vaults for vault in client.list(): id_comps = parse_resource_id(vault.id) if id_comps['name'] == vault_name: return id_comps['resource_group'] return None
def _validator(namespace): from azure.cli.core.commands.arm import parse_resource_id location = namespace.location network_client = get_mgmt_service_client(ResourceType.MGMT_NETWORK).network_watchers watcher = next((x for x in network_client.list_all() if x.location == location), None) if not watcher: raise CLIError("network watcher is not enabled for region '{}'.".format(location)) id_parts = parse_resource_id(watcher.id) setattr(namespace, rg_name, id_parts['resource_group']) setattr(namespace, watcher_name, id_parts['name']) if remove: del namespace.location
def _resolve_api_version_by_id(rcf, resource_id): parts = parse_resource_id(resource_id) if parts.get('grandchild_type'): parent = (parts['type'] + '/' + parts['name'] + '/' + parts['child_type'] + '/' + parts['child_name']) resource_type = parts['grandchild_type'] elif parts.get('child_type'): parent = parts['type'] + '/' + parts['name'] resource_type = parts['child_type'] else: parent = None resource_type = parts['type'] return _ResourceUtils._resolve_api_version(rcf, parts['namespace'], parent, resource_type)
def _get_resource_group_from_account_name(client, account_name): """ Fetch resource group from vault name :param str vault_name: name of the key vault :return: resource group name or None :rtype: str """ for acct in client.list(): id_comps = parse_resource_id(acct.id) if id_comps['name'] == account_name: return id_comps['resource_group'] raise CLIError( "The Resource 'Microsoft.DataLakeStore/accounts/{}'".format(account_name) + " not found within subscription: {}".format(client.config.subscription_id))
def _get_resource_group_from_account_name(client, account_name): """ Fetch resource group from vault name :param str vault_name: name of the key vault :return: resource group name or None :rtype: str """ for acct in client.list(): id_comps = parse_resource_id(acct.id) if id_comps['name'] == account_name: return id_comps['resource_group'] raise CLIError("The Resource 'Microsoft.DataLakeStore/accounts/{}'".format( account_name) + " not found within subscription: {}".format( client.config.subscription_id))
def validate_diagnostic_settings(namespace): from azure.cli.core.commands.client_factory import get_subscription_id resource_group_error = "--resource-group is required when name is provided for "\ "storage account or workspace or service bus namespace and rule. " if namespace.namespace or namespace.rule_name: if namespace.namespace is None: raise CLIError(resource_group_error) if namespace.rule_name is None: raise CLIError(resource_group_error) if namespace.resource_group is None: raise CLIError(resource_group_error) if not is_valid_resource_id(namespace.namespace): namespace.service_bus_rule_id = resource_id(subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.ServiceBus', type='namespaces', name=namespace.namespace, child_type='AuthorizationRules', child_name=namespace.rule_name) else: resource_dict = parse_resource_id(namespace.namespace) namespace.service_bus_rule_id = resource_id(subscription=resource_dict['subscription'], resource_group=resource_dict['resource_group'], namespace=resource_dict['namespace'], type=resource_dict['type'], name=resource_dict['name'], child_type='AuthorizationRules', child_name=namespace.rule_name) if namespace.storage_account and not is_valid_resource_id(namespace.storage_account): if namespace.resource_group is None: raise CLIError(resource_group_error) namespace.storage_account = resource_id(subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.Storage', type='storageAccounts', name=namespace.storage_account) if namespace.workspace and not is_valid_resource_id(namespace.workspace): if namespace.resource_group is None: raise CLIError(resource_group_error) namespace.workspace = resource_id(subscription=get_subscription_id(), resource_group=namespace.resource_group, namespace='microsoft.OperationalInsights', type='workspaces', name=namespace.workspace) _validate_tags(namespace)
def transform_vm_create_output(result): from azure.cli.core.commands.arm import parse_resource_id try: return OrderedDict([ ('id', result.id), ('resourceGroup', getattr(result, 'resource_group', None) or parse_resource_id(result.id)['resource_group']), ('powerState', result.power_state), ('publicIpAddress', result.public_ips), ('fqdns', result.fqdns), ('privateIpAddress', result.private_ips), ('macAddress', result.mac_addresses), ('location', result.location) ]) except AttributeError: from msrest.pipeline import ClientRawResponse return None if isinstance(result, ClientRawResponse) else result
def transform_vm_create_output(result): from azure.cli.core.commands.arm import parse_resource_id try: return OrderedDict([ ('id', result.id), ('resourceGroup', getattr(result, 'resource_group', None) or parse_resource_id(result.id)['resource_group']), ('powerState', result.power_state), ('publicIpAddress', result.public_ips), ('fqdns', result.fqdns), ('privateIpAddress', result.private_ips), ('macAddress', result.mac_addresses), ('location', result.location) ]) except AttributeError: # ClientRawResponse (when using --no-wait) will not have this info return None
def upload_ssl_cert(resource_group_name, name, certificate_password, certificate_file): client = web_client_factory() webapp = _generic_site_operation(resource_group_name, name, 'get') cert_resource_group_name = parse_resource_id(webapp.server_farm_id)['resource_group'] cert_file = open(certificate_file, 'rb') cert_contents = cert_file.read() hosting_environment_profile_param = webapp.hosting_environment_profile if hosting_environment_profile_param is None: hosting_environment_profile_param = "" thumb_print = _get_cert(certificate_password, certificate_file) cert_name = _generate_cert_name(thumb_print, hosting_environment_profile_param, webapp.location, cert_resource_group_name) cert = Certificate(password=certificate_password, pfx_blob=cert_contents, location=webapp.location) return client.certificates.create_or_update(cert_resource_group_name, cert_name, cert)
def _validate_vm_create_availability_set(namespace): from azure.cli.core.commands.client_factory import get_subscription_id if namespace.availability_set: as_id = parse_resource_id(namespace.availability_set) name = as_id['name'] rg = as_id.get('resource_group', namespace.resource_group_name) if not check_existence(name, rg, 'Microsoft.Compute', 'availabilitySets'): raise CLIError("Availability set '{}' does not exist.".format(name)) namespace.availability_set = resource_id( subscription=get_subscription_id(), resource_group=rg, namespace='Microsoft.Compute', type='availabilitySets', name=name)
def vm_show_nic(resource_group_name, vm_name, nic): ''' Show details of a network interface configuration attached to a virtual machine ''' vm = _vm_get(resource_group_name, vm_name) found = next( (n for n in vm.network_profile.network_interfaces if nic.lower() == n.id.lower()), None # pylint: disable=no-member ) if found: from azure.mgmt.network import NetworkManagementClient network_client = get_mgmt_service_client(NetworkManagementClient) nic_name = parse_resource_id(found.id)['name'] return network_client.network_interfaces.get(resource_group_name, nic_name) else: raise CLIError("NIC '{}' not found on VM '{}'".format(nic, vm_name))
def build_msi_role_assignment(vm_vmss_name, vm_vmss_resource_id, role_definition_id, role_assignment_guid, identity_scope, is_vm=True): from azure.cli.core.commands.arm import parse_resource_id from azure.mgmt.authorization import AuthorizationManagementClient from azure.cli.core.commands.client_factory import get_mgmt_service_client result = parse_resource_id(identity_scope) if result.get('type'): # is a resource id? name = '{}/Microsoft.Authorization/{}'.format(result['name'], role_assignment_guid) assignment_type = '{}/{}/providers/roleAssignments'.format( result['namespace'], result['type']) else: name = role_assignment_guid assignment_type = 'Microsoft.Authorization/roleAssignments' # pylint: disable=line-too-long msi_rp_api_version = '2015-08-31-PREVIEW' authorization_api_version = get_mgmt_service_client( AuthorizationManagementClient).config.api_version return { 'name': name, 'type': assignment_type, 'apiVersion': authorization_api_version, 'dependsOn': [ 'Microsoft.Compute/{}/{}'.format( 'virtualMachines' if is_vm else 'virtualMachineScaleSets', vm_vmss_name) ], 'properties': { 'roleDefinitionId': role_definition_id, 'principalId': "[reference('{}/providers/Microsoft.ManagedIdentity/Identities/default', '{}').principalId]" .format(vm_vmss_resource_id, msi_rp_api_version), 'scope': identity_scope } }
def process_nw_flow_log_show_namespace(namespace): from azure.cli.core.commands.arm import parse_resource_id if not is_valid_resource_id(namespace.nsg): namespace.nsg = resource_id( subscription=get_subscription_id(), resource_group=namespace.resource_group_name, namespace='Microsoft.Network', type='networkSecurityGroups', name=namespace.nsg) network_client = get_mgmt_service_client(ResourceType.MGMT_NETWORK).network_security_groups id_parts = parse_resource_id(namespace.nsg) nsg_name = id_parts['name'] rg = id_parts['resource_group'] nsg = network_client.get(rg, nsg_name) namespace.location = nsg.location # pylint: disable=no-member get_network_watcher_from_location(remove=True)(namespace)
def _query_account_key(account_name): scf = get_mgmt_service_client(ResourceType.MGMT_STORAGE) acc = next((x for x in scf.storage_accounts.list() if x.name == account_name), None) if acc: from azure.cli.core.commands.arm import parse_resource_id rg = parse_resource_id(acc.id)['resource_group'] (StorageAccountKeys, StorageAccountListKeysResult) = get_sdk( ResourceType.MGMT_STORAGE, 'models.storage_account_keys#StorageAccountKeys', 'models.storage_account_list_keys_result#StorageAccountListKeysResult') if StorageAccountKeys: return scf.storage_accounts.list_keys(rg, account_name).key1 elif StorageAccountListKeysResult: return scf.storage_accounts.list_keys(rg, account_name).keys[0].value # pylint: disable=no-member else: raise ValueError("Storage account '{}' not found.".format(account_name))
def validate_client_parameters(namespace): """Retrieves Batch connection parameters from environment variables""" from azure.mgmt.batch import BatchManagementClient from azure.cli.core.commands.client_factory import get_mgmt_service_client from azure.cli.core._config import az_config # simply try to retrieve the remaining variables from environment variables if not namespace.account_name: namespace.account_name = az_config.get('batch', 'account', None) if not namespace.account_key: namespace.account_key = az_config.get('batch', 'access_key', None) if not namespace.account_endpoint: namespace.account_endpoint = az_config.get('batch', 'endpoint', None) # if account name is specified but no key, attempt to query if we use shared key auth if namespace.account_name and namespace.account_endpoint and not namespace.account_key: if az_config.get('batch', 'auth_mode', 'shared_key') == 'shared_key': endpoint = urlsplit(namespace.account_endpoint) host = endpoint.netloc client = get_mgmt_service_client(BatchManagementClient) acc = next((x for x in client.batch_account.list() if x.name == namespace.account_name and x.account_endpoint == host), None) if acc: from azure.cli.core.commands.arm import parse_resource_id rg = parse_resource_id(acc.id)['resource_group'] namespace.account_key = \ client.batch_account.get_keys(rg, # pylint: disable=no-member namespace.account_name).primary else: raise ValueError("Batch account '{}' not found.".format( namespace.account_name)) else: if not namespace.account_name: raise ValueError( "Specify batch account in command line or enviroment variable." ) if not namespace.account_endpoint: raise ValueError( "Specify batch endpoint in command line or enviroment variable." ) if az_config.get('batch', 'auth_mode', 'shared_key') == 'aad': namespace.account_key = None
def validate_client_parameters(namespace): """ Retrieves storage connection parameters from environment variables and parses out connection string into account name and key """ n = namespace if not n.connection_string: n.connection_string = az_config.get('storage', 'connection_string', None) # if connection string supplied or in environment variables, extract account key and name if n.connection_string: conn_dict = validate_key_value_pairs(n.connection_string) n.account_name = conn_dict['AccountName'] n.account_key = conn_dict['AccountKey'] # otherwise, simply try to retrieve the remaining variables from environment variables if not n.account_name: n.account_name = az_config.get('storage', 'account', None) if not n.account_key: n.account_key = az_config.get('storage', 'key', None) if not n.sas_token: n.sas_token = az_config.get('storage', 'sas_token', None) # strip the '?' from sas token. the portal and command line are returns sas token in different # forms if n.sas_token: n.sas_token = n.sas_token.lstrip('?') # if account name is specified but no key, attempt to query if n.account_name and not n.account_key and not n.sas_token: scf = get_mgmt_service_client(StorageManagementClient) acc = next( (x for x in scf.storage_accounts.list() if x.name == n.account_name), None) if acc: from azure.cli.core.commands.arm import parse_resource_id rg = parse_resource_id(acc.id)['resource_group'] n.account_key = \ scf.storage_accounts.list_keys(rg, n.account_name).keys[0].value # pylint: disable=no-member else: raise ValueError("Storage account '{}' not found.".format( n.account_name))
def _resolve_api_version_by_id(rcf, resource_id): parts = parse_resource_id(resource_id) namespace = parts.get('child_namespace', parts['namespace']) if parts.get('grandchild_type'): parent = (parts['type'] + '/' + parts['name'] + '/' + parts['child_type'] + '/' + parts['child_name']) resource_type = parts['grandchild_type'] elif parts.get('child_type'): # if the child resource has a provider namespace it is independent of the # parent, so set the parent to empty if parts.get('child_namespace') is not None: parent = '' else: parent = parts['type'] + '/' + parts['name'] resource_type = parts['child_type'] else: parent = None resource_type = parts['type'] return _ResourceUtils.resolve_api_version(rcf, namespace, parent, resource_type)
def upload_ssl_cert(resource_group_name, name, certificate_password, certificate_file): client = web_client_factory() webapp = _generic_site_operation(resource_group_name, name, 'get') cert_resource_group_name = parse_resource_id( webapp.server_farm_id)['resource_group'] cert_file = open(certificate_file, 'rb') cert_contents = cert_file.read() hosting_environment_profile_param = webapp.hosting_environment_profile if hosting_environment_profile_param is None: hosting_environment_profile_param = "" thumb_print = _get_cert(certificate_password, certificate_file) cert_name = _generate_cert_name(thumb_print, hosting_environment_profile_param, webapp.location, cert_resource_group_name) cert = Certificate(password=certificate_password, pfx_blob=cert_contents, location=webapp.location) return client.certificates.create_or_update(cert_resource_group_name, cert_name, cert)
def transform_vm_create_output(result): from azure.cli.core.commands.arm import parse_resource_id try: output = OrderedDict([ ('id', result.id), ('resourceGroup', getattr(result, 'resource_group', None) or parse_resource_id(result.id)['resource_group']), ('powerState', result.power_state), ('publicIpAddress', result.public_ips), ('fqdns', result.fqdns), ('privateIpAddress', result.private_ips), ('macAddress', result.mac_addresses), ('location', result.location) ]) if getattr(result, 'identity', None): output['identity'] = result.identity if hasattr(result, 'zones' ): # output 'zones' column even the property value is None output['zones'] = result.zones[0] if result.zones else '' return output except AttributeError: from msrest.pipeline import ClientRawResponse return None if isinstance(result, ClientRawResponse) else result
def _validate_vm_create_storage_account(namespace): if namespace.storage_account: storage_id = parse_resource_id(namespace.storage_account) rg = storage_id.get('resource_group', namespace.resource_group_name) if check_existence(storage_id['name'], rg, 'Microsoft.Storage', 'storageAccounts'): # 1 - existing storage account specified namespace.storage_account_type = 'existing' logger.debug("using specified existing storage account '%s'", storage_id['name']) else: # 2 - params for new storage account specified namespace.storage_account_type = 'new' logger.debug( "specified storage account '%s' not found and will be created", storage_id['name']) else: from azure.cli.core.profiles import ResourceType from azure.cli.core.commands.client_factory import get_mgmt_service_client storage_client = get_mgmt_service_client( ResourceType.MGMT_STORAGE).storage_accounts # find storage account in target resource group that matches the VM's location sku_tier = 'Premium' if 'Premium' in namespace.storage_sku else 'Standard' account = next((a for a in storage_client.list_by_resource_group( namespace.resource_group_name) if a.sku.tier.value == sku_tier and a.location == namespace.location), None) if account: # 3 - nothing specified - find viable storage account in target resource group namespace.storage_account = account.name namespace.storage_account_type = 'existing' logger.debug("suitable existing storage account '%s' will be used", account.name) else: # 4 - nothing specified - create a new storage account namespace.storage_account_type = 'new' logger.debug( 'no suitable storage account found. One will be created.')
def list_policy_assignment(disable_scope_strict_match=None, resource_group_name=None, scope=None): policy_client = _resource_policy_client_factory() if scope and not is_valid_resource_id(scope): parts = scope.strip('/').split('/') if len(parts) == 4: resource_group_name = parts[3] elif len(parts) == 2: #rarely used, but still verify if parts[1].lower() != policy_client.config.subscription_id.lower( ): raise CLIError("Please use current active subscription's id") else: err = "Invalid scope '{}', it should point to a resource group or a resource" raise CLIError(err.format(scope)) scope = None _scope = _build_policy_scope(policy_client.config.subscription_id, resource_group_name, scope) if resource_group_name: result = policy_client.policy_assignments.list_for_resource_group( resource_group_name) elif scope: #pylint: disable=redefined-builtin id = parse_resource_id(scope) parent_resource_path = '' if not id.get('child_name') else ( id['type'] + '/' + id['name']) resource_type = id.get('child_type') or id['type'] resource_name = id.get('child_name') or id['name'] result = policy_client.policy_assignments.list_for_resource( id['resource_group'], id['namespace'], parent_resource_path, resource_type, resource_name) else: result = policy_client.policy_assignments.list() if not disable_scope_strict_match: result = [i for i in result if _scope.lower() == i.scope.lower()] return result
def _server_restore(client, resource_group_name, server_name, parameters, **kwargs): """ Create a new server by restoring from a server backup. """ source_server = kwargs['source_server_id'] if not is_valid_resource_id(source_server): if len(source_server.split('/')) == 1: from azure.cli.core.commands.client_factory import get_subscription_id from azure.mgmt.rdbms.mysql.operations.servers_operations import ServersOperations provider = 'Microsoft.DBForMySQL' if isinstance( client, ServersOperations) else 'Microsoft.DBforPostgreSQL' source_server = resource_id(subscription=get_subscription_id(), resource_group=resource_group_name, namespace=provider, type='servers', name=source_server) else: raise ValueError( 'The provided source-server {} is invalid.'.format( source_server)) parameters.properties.source_server_id = source_server # Here is a workaround that we don't support cross-region restore currently, # so the location must be set as the same as source server (not the resource group) id_parts = parse_resource_id(source_server) try: source_server_object = client.get(id_parts['resource_group'], id_parts['name']) parameters.location = source_server_object.location except Exception as e: raise ValueError('Unable to get source server: {}.'.format(str(e))) return client.create_or_update(resource_group_name, server_name, parameters)