From 64f3fe3fa8fc88e98186885bf43a96a75489107d Mon Sep 17 00:00:00 2001
From: ed lane <ed.lane.0@gmail.com>
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 | 47 +++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
index 0345f1d277..794af1fc88 100644
--- a/salt/cloud/clouds/azurearm.py
+++ b/salt/cloud/clouds/azurearm.py
@@ -25,6 +25,9 @@ The Azure cloud module is used to control access to Microsoft Azure
     * ``client_id``
     * ``secret``
 
+    if using MSI-style authentication:
+    * ``subscription_id``
+
 Example ``/etc/salt/cloud.providers`` or
 ``/etc/salt/cloud.providers.d/azure.conf`` configuration:
 
@@ -48,6 +51,10 @@ Example ``/etc/salt/cloud.providers`` or
       For example, this creates a service principal with 'owner' role for the whole subscription:
       az ad sp create-for-rbac -n "http://mysaltapp" --role owner --scopes /subscriptions/3287abc8-f98a-c678-3bde-326766fd3617
       *Note: review the details of Service Principals. Owner role is more than you normally need, and you can restrict scope to a resource group or individual resources.
+
+    Or my-azure-config with MSI-style authentication:
+      driver: azure
+      subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617
 '''
 # pylint: disable=E0102
 
@@ -85,6 +92,7 @@ try:
         UserPassCredentials,
         ServicePrincipalCredentials,
     )
+    from msrestazure.azure_active_directory import MSIAuthentication
     from azure.mgmt.compute import ComputeManagementClient
     from azure.mgmt.compute.models import (
         CachingTypes,
@@ -165,19 +173,30 @@ def get_configured_provider():
     '''
     Return the first configured instance.
     '''
+    # check if using Service Principle style authentication...
     provider = config.is_provider_configured(
         __opts__,
         __active_provider_name__ or __virtualname__,
-        ('subscription_id', 'tenant', 'client_id', 'secret')
+        required_keys=('subscription_id', 'tenant', 'client_id', 'secret'),
+        log_message=False  #... allowed to fail so no need to log warnings
         )
     if provider is False:
-        return config.is_provider_configured(
+        # check if using username/password style authentication...
+        provider = config.is_provider_configured(
             __opts__,
             __active_provider_name__ or __virtualname__,
-            ('subscription_id', 'username', 'password')
+            required_keys=('subscription_id', 'username', 'password'),
+            log_message=False
         )
-    else:
-        return provider
+    if provider is False:
+        # check if using MSI style credentials...
+        provider = config.is_provider_configured(
+            __opts__,
+            __active_provider_name__ or __virtualname__,
+            required_keys=('subscription_id',),
+            log_message=False
+        )
+    return provider
 
 
 def get_dependencies():
@@ -207,6 +226,7 @@ def get_conn(Client=None):
         get_configured_provider(), __opts__, search_global=False
     )
     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
@@ -221,15 +241,20 @@ def get_conn(Client=None):
             'username',
             get_configured_provider(), __opts__, search_global=False
         )
-        password = config.get_cloud_config_value(
-            'password',
-            get_configured_provider(), __opts__, search_global=False
-        )
-        credentials = UserPassCredentials(username, password)
+        if username is not None:
+            # using username/password style authentication...
+            password = config.get_cloud_config_value(
+                'password',
+                get_configured_provider(), __opts__, search_global=False
+            )
+            credentials = UserPassCredentials(username, password)
+        else:
+            # using MSI style authentication ...
+            credentials = MSIAuthentication()
 
     client = Client(
         credentials=credentials,
-        subscription_id=subscription_id,
+        subscription_id=str(subscription_id),
     )
     client.config.add_user_agent('SaltCloud/{0}'.format(salt.version.__version__))
     return client
-- 
2.18.0


