Support MSI for ansible on Azure resources (#36634)

* msi

* add env and param

* add msi in default

* add azure_rm

* add document

* subscription param

* if not enabled msi

* remove the msi in default mode since the infinite loop will block if not enabled msi

* lint

* lint

* Update azure_rm_common.py

* fix

* catch exc and make error message more friendly

* lint

* Minor docs changes to the msi source option
pull/37793/head
Yuwei Zhou 7 years ago committed by Jordan Borean
parent 05220d693d
commit 8c819dd9cb

@ -23,7 +23,7 @@ except ImportError:
AZURE_COMMON_ARGS = dict( AZURE_COMMON_ARGS = dict(
auth_source=dict( auth_source=dict(
type='str', type='str',
choices=['auto', 'cli', 'env', 'credential_file'] choices=['auto', 'cli', 'env', 'credential_file', 'msi']
), ),
profile=dict(type='str'), profile=dict(type='str'),
subscription_id=dict(type='str', no_log=True), subscription_id=dict(type='str', no_log=True),
@ -127,6 +127,7 @@ except ImportError as exc:
try: try:
from enum import Enum from enum import Enum
from msrestazure.azure_exceptions import CloudError from msrestazure.azure_exceptions import CloudError
from msrestazure.azure_active_directory import MSIAuthentication
from msrestazure.tools import resource_id, is_valid_resource_id from msrestazure.tools import resource_id, is_valid_resource_id
from msrestazure import azure_cloud from msrestazure import azure_cloud
from azure.common.credentials import ServicePrincipalCredentials, UserPassCredentials from azure.common.credentials import ServicePrincipalCredentials, UserPassCredentials
@ -138,6 +139,7 @@ try:
from azure.mgmt.web.version import VERSION as web_client_version from azure.mgmt.web.version import VERSION as web_client_version
from azure.mgmt.network import NetworkManagementClient from azure.mgmt.network import NetworkManagementClient
from azure.mgmt.resource.resources import ResourceManagementClient from azure.mgmt.resource.resources import ResourceManagementClient
from azure.mgmt.resource.subscriptions import SubscriptionClient
from azure.mgmt.storage import StorageManagementClient from azure.mgmt.storage import StorageManagementClient
from azure.mgmt.compute import ComputeManagementClient from azure.mgmt.compute import ComputeManagementClient
from azure.mgmt.dns import DnsManagementClient from azure.mgmt.dns import DnsManagementClient
@ -489,6 +491,23 @@ class AzureRMModuleBase(object):
return None return None
def _get_msi_credentials(self, subscription_id_param=None):
credentials = MSIAuthentication()
subscription_id = subscription_id_param or os.environ.get(AZURE_CREDENTIAL_ENV_MAPPING['subscription_id'], None)
if not subscription_id:
try:
# use the first subscription of the MSI
subscription_client = SubscriptionClient(credentials)
subscription = next(subscription_client.subscriptions.list())
subscription_id = str(subscription.subscription_id)
except Exception as exc:
self.fail("Failed to get MSI token: {0}. "
"Please check whether your machine enabled MSI or grant access to any subscription.".format(str(exc)))
return {
'credentials': credentials,
'subscription_id': subscription_id
}
def _get_azure_cli_credentials(self): def _get_azure_cli_credentials(self):
credentials, subscription_id = get_azure_cli_credentials() credentials, subscription_id = get_azure_cli_credentials()
cloud_environment = get_cli_active_cloud() cloud_environment = get_cli_active_cloud()
@ -526,6 +545,10 @@ class AzureRMModuleBase(object):
if not auth_source: if not auth_source:
auth_source = os.environ.get('ANSIBLE_AZURE_AUTH_SOURCE', 'auto') auth_source = os.environ.get('ANSIBLE_AZURE_AUTH_SOURCE', 'auto')
if auth_source == 'msi':
self.log('Retrieving credenitals from MSI')
return self._get_msi_credentials(arg_credentials['subscription_id'])
if auth_source == 'cli': if auth_source == 'cli':
if not HAS_AZURE_CLI_CORE: if not HAS_AZURE_CLI_CORE:
self.fail("Azure auth_source is `cli`, but azure-cli package is not available. Try `pip install azure-cli --upgrade`") self.fail("Azure auth_source is `cli`, but azure-cli package is not available. Try `pip install azure-cli --upgrade`")

@ -68,11 +68,16 @@ options:
C(~/.azure/credentials). C(~/.azure/credentials).
- When set to C(cli), the credentials will be sources from the default Azure CLI profile. - When set to C(cli), the credentials will be sources from the default Azure CLI profile.
- Can also be set via the C(ANSIBLE_AZURE_AUTH_SOURCE) environment variable. - Can also be set via the C(ANSIBLE_AZURE_AUTH_SOURCE) environment variable.
- When set to C(msi), the host machine must be an azure resource with an enabled MSI extension. C(subscription_id) or the
environment variable C(AZURE_SUBSCRIPTION_ID) can be used to identify the subscription ID if the resource is granted
access to more than one subscription, otherwise the first subscription is chosen.
- The C(msi) was added in Ansible 2.6.
choices: choices:
- auto - auto
- cli - cli
- credential_file - credential_file
- env - env
- msi
default: auto default: auto
version_added: 2.5 version_added: 2.5
api_profile: api_profile:

Loading…
Cancel
Save