From bb2070d4f4e8fbb5a963c521d61feb7419abdec1 Mon Sep 17 00:00:00 2001 From: ed lane Date: Thu, 30 Aug 2018 06:07:08 -0600 Subject: [PATCH] Integration of MSI authentication with azurearm cloud driver (#105) --- salt/cloud/clouds/azurearm.py | 98 +++++++++++++++-------------------- 1 file changed, 43 insertions(+), 55 deletions(-) diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py index 54fc7b497b..8b9254cecb 100644 --- a/salt/cloud/clouds/azurearm.py +++ b/salt/cloud/clouds/azurearm.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Azure ARM Cloud Module ====================== @@ -61,6 +60,9 @@ The Azure ARM cloud module is used to control access to Microsoft Azure Resource virtual machine type will be "Windows". Only set this parameter on profiles which install Windows operating systems. + if using MSI-style authentication: + * ``subscription_id`` + Example ``/etc/salt/cloud.providers`` or ``/etc/salt/cloud.providers.d/azure.conf`` configuration: @@ -91,7 +93,6 @@ Example ``/etc/salt/cloud.providers`` or # pylint: disable=wrong-import-position,wrong-import-order -from __future__ import absolute_import, print_function, unicode_literals import importlib import logging @@ -121,7 +122,6 @@ from salt.exceptions import ( # Salt libs from salt.ext import six -# Import 3rd-party libs HAS_LIBS = False try: import azure.mgmt.compute.models as compute_models @@ -179,7 +179,7 @@ def get_api_versions(call=None, kwargs=None): # pylint: disable=unused-argument ) for resource in provider_query.resource_types: - if six.text_type(resource.resource_type) == kwargs["resource_type"]: + if str(resource.resource_type) == kwargs["resource_type"]: resource_dict = resource.as_dict() api_versions = resource_dict["api_versions"] except CloudError as exc: @@ -263,6 +263,7 @@ def get_conn(client_type): ) if tenant is not None: + # using Service Principle style authentication... client_id = config.get_cloud_config_value( "client_id", get_configured_provider(), __opts__, search_global=False ) @@ -319,7 +320,7 @@ def avail_locations(call=None): ) locations = [] for resource in provider_query.resource_types: - if six.text_type(resource.resource_type) == "virtualMachines": + if str(resource.resource_type) == "virtualMachines": resource_dict = resource.as_dict() locations = resource_dict["locations"] for location in locations: @@ -399,7 +400,7 @@ def avail_images(call=None): results = pool.map_async(_get_publisher_images, publishers) results.wait() - ret = {k: v for result in results.get() for k, v in six.iteritems(result)} + ret = {k: v for result in results.get() for k, v in result.items()} return ret @@ -529,7 +530,7 @@ def list_nodes_full(call=None): results = pool.map_async(_get_node_info, nodes) results.wait() - group_ret = {k: v for result in results.get() for k, v in six.iteritems(result)} + group_ret = {k: v for result in results.get() for k, v in result.items()} ret.update(group_ret) return ret @@ -707,7 +708,7 @@ def create_network_interface(call=None, kwargs=None): ) if kwargs.get("iface_name") is None: - kwargs["iface_name"] = "{0}-iface0".format(vm_["name"]) + kwargs["iface_name"] = "{}-iface0".format(vm_["name"]) try: subnet_obj = netconn.subnets.get( @@ -717,7 +718,7 @@ def create_network_interface(call=None, kwargs=None): ) except CloudError as exc: raise SaltCloudSystemExit( - '{0} (Resource Group: "{1}", VNET: "{2}", Subnet: "{3}")'.format( + '{} (Resource Group: "{}", VNET: "{}", Subnet: "{}")'.format( exc.message, kwargs["network_resource_group"], kwargs["network"], @@ -740,11 +741,11 @@ def create_network_interface(call=None, kwargs=None): ) pool_ids.append({"id": lbbep_data.as_dict()["id"]}) except CloudError as exc: - log.error("There was a cloud error: %s", six.text_type(exc)) + log.error("There was a cloud error: %s", str(exc)) except KeyError as exc: log.error( "There was an error getting the Backend Pool ID: %s", - six.text_type(exc), + str(exc), ) ip_kwargs["load_balancer_backend_address_pools"] = pool_ids @@ -755,7 +756,7 @@ def create_network_interface(call=None, kwargs=None): ip_kwargs["private_ip_allocation_method"] = IPAllocationMethod.dynamic if kwargs.get("allocate_public_ip") is True: - pub_ip_name = "{0}-ip".format(kwargs["iface_name"]) + pub_ip_name = "{}-ip".format(kwargs["iface_name"]) poller = netconn.public_ip_addresses.create_or_update( resource_group_name=kwargs["resource_group"], public_ip_address_name=pub_ip_name, @@ -773,11 +774,11 @@ def create_network_interface(call=None, kwargs=None): ) if pub_ip_data.ip_address: # pylint: disable=no-member ip_kwargs["public_ip_address"] = PublicIPAddress( - id=six.text_type(pub_ip_data.id), # pylint: disable=no-member + id=str(pub_ip_data.id), # pylint: disable=no-member ) ip_configurations = [ NetworkInterfaceIPConfiguration( - name="{0}-ip".format(kwargs["iface_name"]), + name="{}-ip".format(kwargs["iface_name"]), subnet=subnet_obj, **ip_kwargs ) @@ -790,7 +791,7 @@ def create_network_interface(call=None, kwargs=None): raise ValueError("Timed out waiting for public IP Address.") time.sleep(5) else: - priv_ip_name = "{0}-ip".format(kwargs["iface_name"]) + priv_ip_name = "{}-ip".format(kwargs["iface_name"]) ip_configurations = [ NetworkInterfaceIPConfiguration( name=priv_ip_name, subnet=subnet_obj, **ip_kwargs @@ -900,7 +901,7 @@ def request_instance(vm_): ) vm_["iface_id"] = iface_data["id"] - disk_name = "{0}-vol0".format(vm_["name"]) + disk_name = "{}-vol0".format(vm_["name"]) vm_username = config.get_cloud_config_value( "ssh_username", @@ -922,8 +923,8 @@ def request_instance(vm_): ssh_publickeyfile_contents = spkc_.read() except Exception as exc: # pylint: disable=broad-except raise SaltCloudConfigError( - "Failed to read ssh publickey file '{0}': " - "{1}".format(ssh_publickeyfile, exc.args[-1]) + "Failed to read ssh publickey file '{}': " + "{}".format(ssh_publickeyfile, exc.args[-1]) ) disable_password_authentication = config.get_cloud_config_value( @@ -941,7 +942,7 @@ def request_instance(vm_): if not win_installer and ssh_publickeyfile_contents is not None: sshpublickey = SshPublicKey( key_data=ssh_publickeyfile_contents, - path="/home/{0}/.ssh/authorized_keys".format(vm_username), + path="/home/{}/.ssh/authorized_keys".format(vm_username), ) sshconfiguration = SshConfiguration(public_keys=[sshpublickey],) linuxconfiguration = LinuxConfiguration( @@ -991,9 +992,9 @@ def request_instance(vm_): availability_set = config.get_cloud_config_value( "availability_set", vm_, __opts__, search_global=False, default=None ) - if availability_set is not None and isinstance(availability_set, six.string_types): + if availability_set is not None and isinstance(availability_set, str): availability_set = { - "id": "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/availabilitySets/{2}".format( + "id": "/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/availabilitySets/{}".format( subscription_id, vm_["resource_group"], availability_set ) } @@ -1004,7 +1005,7 @@ def request_instance(vm_): storage_endpoint_suffix = cloud_env.suffixes.storage_endpoint - if isinstance(vm_.get("volumes"), six.string_types): + if isinstance(vm_.get("volumes"), str): volumes = salt.utils.yaml.safe_load(vm_["volumes"]) else: volumes = vm_.get("volumes") @@ -1018,16 +1019,14 @@ def request_instance(vm_): lun = 0 luns = [] for volume in volumes: - if isinstance(volume, six.string_types): + if isinstance(volume, str): volume = {"name": volume} volume.setdefault( "name", volume.get( "name", - volume.get( - "name", "{0}-datadisk{1}".format(vm_["name"], six.text_type(lun)) - ), + volume.get("name", "{}-datadisk{}".format(vm_["name"], str(lun))), ), ) @@ -1050,7 +1049,7 @@ def request_instance(vm_): del volume["media_link"] elif volume.get("vhd") == "unmanaged": volume["vhd"] = VirtualHardDisk( - uri="https://{0}.blob.{1}/vhds/{2}-datadisk{3}.vhd".format( + uri="https://{}.blob.{}/vhds/{}-datadisk{}.vhd".format( vm_["storage_account"], storage_endpoint_suffix, vm_["name"], @@ -1090,7 +1089,7 @@ def request_instance(vm_): create_option=DiskCreateOptionTypes.from_image, name=disk_name, vhd=VirtualHardDisk( - uri="https://{0}.blob.{1}/vhds/{2}.vhd".format( + uri="https://{}.blob.{}/vhds/{}.vhd".format( vm_["storage_account"], storage_endpoint_suffix, disk_name, ), ), @@ -1209,7 +1208,7 @@ def request_instance(vm_): __utils__["cloud.fire_event"]( "event", "requesting instance", - "salt/cloud/{0}/requesting".format(vm_["name"]), + "salt/cloud/{}/requesting".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "requesting", vm_, ["name", "profile", "provider", "driver"] ), @@ -1260,7 +1259,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "starting create", - "salt/cloud/{0}/creating".format(vm_["name"]), + "salt/cloud/{}/creating".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "creating", vm_, ["name", "profile", "provider", "driver"] ), @@ -1278,9 +1277,7 @@ def create(vm_): vm_request = request_instance(vm_=vm_) if not vm_request or "error" in vm_request: - err_message = "Error creating VM {0}! ({1})".format( - vm_["name"], six.text_type(vm_request) - ) + err_message = "Error creating VM {}! ({})".format(vm_["name"], str(vm_request)) log.error(err_message) raise SaltCloudSystemExit(err_message) @@ -1322,7 +1319,7 @@ def create(vm_): try: log.warning(exc) finally: - raise SaltCloudSystemExit(six.text_type(exc)) + raise SaltCloudSystemExit(str(exc)) vm_["ssh_host"] = data if not vm_.get("ssh_username"): @@ -1341,7 +1338,7 @@ def create(vm_): __utils__["cloud.fire_event"]( "event", "created instance", - "salt/cloud/{0}/created".format(vm_["name"]), + "salt/cloud/{}/created".format(vm_["name"]), args=__utils__["cloud.filter_event"]( "created", vm_, ["name", "profile", "provider", "driver"] ), @@ -1548,9 +1545,7 @@ def _get_cloud_environment(): cloud_env = getattr(cloud_env_module, cloud_environment or "AZURE_PUBLIC_CLOUD") except (AttributeError, ImportError): raise SaltCloudSystemExit( - "The azure {0} cloud environment is not available.".format( - cloud_environment - ) + "The azure {} cloud environment is not available.".format(cloud_environment) ) return cloud_env @@ -1585,7 +1580,7 @@ def _get_block_blob_service(kwargs=None): resource_group, storage_account ) storage_keys = {v.key_name: v.value for v in storage_keys.keys} - storage_key = next(six.itervalues(storage_keys)) + storage_key = next(iter(storage_keys.values())) cloud_env = _get_cloud_environment() @@ -1620,7 +1615,7 @@ def list_blobs(call=None, kwargs=None): # pylint: disable=unused-argument "server_encrypted": blob.properties.server_encrypted, } except Exception as exc: # pylint: disable=broad-except - log.warning(six.text_type(exc)) + log.warning(str(exc)) return ret @@ -1655,9 +1650,7 @@ def delete_managed_disk(call=None, kwargs=None): # pylint: disable=unused-argum compconn.disks.delete(kwargs["resource_group"], kwargs["blob"]) except Exception as exc: # pylint: disable=broad-except log.error( - "Error deleting managed disk %s - %s", - kwargs.get("blob"), - six.text_type(exc), + "Error deleting managed disk %s - %s", kwargs.get("blob"), str(exc), ) return False @@ -1834,7 +1827,7 @@ def create_or_update_vmextension( except CloudError as exc: __utils__["azurearm.log_cloud_error"]( "compute", - "Error attempting to create the VM extension: {0}".format(exc.message), + "Error attempting to create the VM extension: {}".format(exc.message), ) ret = {"error": exc.message} @@ -1881,11 +1874,9 @@ def stop(name, call=None): ret = {"error": exc.message} if not ret: __utils__["azurearm.log_cloud_error"]( - "compute", "Unable to find virtual machine with name: {0}".format(name) + "compute", "Unable to find virtual machine with name: {}".format(name) ) - ret = { - "error": "Unable to find virtual machine with name: {0}".format(name) - } + ret = {"error": "Unable to find virtual machine with name: {}".format(name)} else: try: instance = compconn.virtual_machines.deallocate( @@ -1896,7 +1887,7 @@ def stop(name, call=None): ret = vm_result.as_dict() except CloudError as exc: __utils__["azurearm.log_cloud_error"]( - "compute", "Error attempting to stop {0}: {1}".format(name, exc.message) + "compute", "Error attempting to stop {}: {}".format(name, exc.message) ) ret = {"error": exc.message} @@ -1945,11 +1936,9 @@ def start(name, call=None): ret = {"error": exc.message} if not ret: __utils__["azurearm.log_cloud_error"]( - "compute", "Unable to find virtual machine with name: {0}".format(name) + "compute", "Unable to find virtual machine with name: {}".format(name) ) - ret = { - "error": "Unable to find virtual machine with name: {0}".format(name) - } + ret = {"error": "Unable to find virtual machine with name: {}".format(name)} else: try: instance = compconn.virtual_machines.start( @@ -1960,8 +1949,7 @@ def start(name, call=None): ret = vm_result.as_dict() except CloudError as exc: __utils__["azurearm.log_cloud_error"]( - "compute", - "Error attempting to start {0}: {1}".format(name, exc.message), + "compute", "Error attempting to start {}: {}".format(name, exc.message), ) ret = {"error": exc.message} -- 2.29.2