mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Azure: added auth_source to override the source of the credentials (#35213)
* Azure: added auth_source to override the source of the credentials * removed broken cli auth and fix some review changes * missed some more cli auth stuff that isn't required * Added cli auth back in * Added docs around cli auth * fix azure CLI auth issues * tweak error messages * fix auto fallback to cli * fix import issues when azure-cli not installed
This commit is contained in:
parent
8c7bd8beb4
commit
9e48cf875f
2 changed files with 84 additions and 36 deletions
|
@ -35,7 +35,10 @@ except ImportError:
|
|||
ANSIBLE_VERSION = 'unknown'
|
||||
|
||||
AZURE_COMMON_ARGS = dict(
|
||||
cli_default_profile=dict(type='bool'),
|
||||
auth_source=dict(
|
||||
type='str',
|
||||
choices=['auto', 'cli', 'env', 'credential_file']
|
||||
),
|
||||
profile=dict(type='str'),
|
||||
subscription_id=dict(type='str', no_log=True),
|
||||
client_id=dict(type='str', no_log=True),
|
||||
|
@ -49,7 +52,6 @@ AZURE_COMMON_ARGS = dict(
|
|||
)
|
||||
|
||||
AZURE_CREDENTIAL_ENV_MAPPING = dict(
|
||||
cli_default_profile='AZURE_CLI_DEFAULT_PROFILE',
|
||||
profile='AZURE_PROFILE',
|
||||
subscription_id='AZURE_SUBSCRIPTION_ID',
|
||||
client_id='AZURE_CLIENT_ID',
|
||||
|
@ -134,13 +136,13 @@ except ImportError as exc:
|
|||
HAS_AZURE_EXC = exc
|
||||
HAS_AZURE = False
|
||||
|
||||
|
||||
try:
|
||||
from azure.cli.core.util import CLIError
|
||||
from azure.common.credentials import get_azure_cli_credentials, get_cli_profile
|
||||
from azure.common.cloud import get_cli_active_cloud
|
||||
except ImportError:
|
||||
HAS_AZURE_CLI_CORE = False
|
||||
CLIError = Exception
|
||||
|
||||
|
||||
def azure_id_to_dict(id):
|
||||
|
@ -254,8 +256,12 @@ class AzureRMModuleBase(object):
|
|||
# authenticate
|
||||
self.credentials = self._get_credentials(self.module.params)
|
||||
if not self.credentials:
|
||||
self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
|
||||
"or define a profile in ~/.azure/credentials or be logged using AzureCLI.")
|
||||
if HAS_AZURE_CLI_CORE:
|
||||
self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
|
||||
"define a profile in ~/.azure/credentials, or log in with Azure CLI (`az login`).")
|
||||
else:
|
||||
self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
|
||||
"define a profile in ~/.azure/credentials, or install Azure CLI and log in (`az login`).")
|
||||
|
||||
# cert validation mode precedence: module-arg, credential profile, env, "validate"
|
||||
self._cert_validation_mode = self.module.params['cert_validation_mode'] or self.credentials.get('cert_validation_mode') or \
|
||||
|
@ -266,7 +272,9 @@ class AzureRMModuleBase(object):
|
|||
|
||||
# if cloud_environment specified, look up/build Cloud object
|
||||
raw_cloud_env = self.credentials.get('cloud_environment')
|
||||
if not raw_cloud_env:
|
||||
if self.credentials.get('credentials') is not None and raw_cloud_env is not None:
|
||||
self._cloud_environment = raw_cloud_env
|
||||
elif not raw_cloud_env:
|
||||
self._cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD # SDK default
|
||||
else:
|
||||
# try to look up "well-known" values via the name attribute on azure_cloud members
|
||||
|
@ -284,19 +292,22 @@ class AzureRMModuleBase(object):
|
|||
except Exception as e:
|
||||
self.fail("cloud_environment {0} could not be resolved: {1}".format(raw_cloud_env, e.message), exception=traceback.format_exc(e))
|
||||
|
||||
if self.credentials.get('subscription_id', None) is None:
|
||||
if self.credentials.get('subscription_id', None) is None and self.credentials.get('credentials') is None:
|
||||
self.fail("Credentials did not include a subscription_id value.")
|
||||
self.log("setting subscription_id")
|
||||
self.subscription_id = self.credentials['subscription_id']
|
||||
|
||||
if self.credentials.get('client_id') is not None and \
|
||||
self.credentials.get('secret') is not None and \
|
||||
self.credentials.get('tenant') is not None:
|
||||
self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'],
|
||||
secret=self.credentials['secret'],
|
||||
tenant=self.credentials['tenant'],
|
||||
cloud_environment=self._cloud_environment,
|
||||
verify=self._cert_validation_mode == 'validate')
|
||||
if self.credentials.get('credentials') is not None:
|
||||
# AzureCLI credentials
|
||||
self.azure_credentials = self.credentials['credentials']
|
||||
elif self.credentials.get('client_id') is not None and \
|
||||
self.credentials.get('secret') is not None and \
|
||||
self.credentials.get('tenant') is not None:
|
||||
self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'],
|
||||
secret=self.credentials['secret'],
|
||||
tenant=self.credentials['tenant'],
|
||||
cloud_environment=self._cloud_environment,
|
||||
verify=self._cert_validation_mode == 'validate')
|
||||
|
||||
elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None:
|
||||
tenant = self.credentials.get('tenant')
|
||||
|
@ -437,19 +448,6 @@ class AzureRMModuleBase(object):
|
|||
except Exception as exc:
|
||||
self.fail("Error retrieving resource group {0} - {1}".format(resource_group, str(exc)))
|
||||
|
||||
def _get_azure_cli_profile(self):
|
||||
if not HAS_AZURE_CLI_CORE:
|
||||
self.fail("Do you have azure-cli-core installed? Try `pip install 'azure-cli-core' --upgrade`")
|
||||
try:
|
||||
credentials, subscription_id = get_azure_cli_credentials()
|
||||
self._cloud_environment = get_cli_active_cloud()
|
||||
return {
|
||||
'credentials': credentials,
|
||||
'subscription_id': subscription_id
|
||||
}
|
||||
except CLIError as err:
|
||||
self.fail("AzureCLI profile cannot be loaded - {0}".format(err))
|
||||
|
||||
def _get_profile(self, profile="default"):
|
||||
path = expanduser("~/.azure/credentials")
|
||||
try:
|
||||
|
@ -470,14 +468,22 @@ class AzureRMModuleBase(object):
|
|||
|
||||
return None
|
||||
|
||||
def _get_azure_cli_credentials(self):
|
||||
credentials, subscription_id = get_azure_cli_credentials()
|
||||
cloud_environment = get_cli_active_cloud()
|
||||
|
||||
cli_credentials = {
|
||||
'credentials': credentials,
|
||||
'subscription_id': subscription_id,
|
||||
'cloud_environment': cloud_environment
|
||||
}
|
||||
return cli_credentials
|
||||
|
||||
def _get_env_credentials(self):
|
||||
env_credentials = dict()
|
||||
for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
|
||||
env_credentials[attribute] = os.environ.get(env_variable, None)
|
||||
|
||||
if (env_credentials['cli_default_profile'] or '').lower() in ["true", "yes", "1"]:
|
||||
return self._get_azure_cli_profile()
|
||||
|
||||
if env_credentials['profile']:
|
||||
credentials = self._get_profile(env_credentials['profile'])
|
||||
return credentials
|
||||
|
@ -489,18 +495,38 @@ class AzureRMModuleBase(object):
|
|||
|
||||
def _get_credentials(self, params):
|
||||
# Get authentication credentials.
|
||||
# Precedence: module parameters-> environment variables-> default profile in ~/.azure/credentials.
|
||||
|
||||
self.log('Getting credentials')
|
||||
|
||||
arg_credentials = dict()
|
||||
for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
|
||||
arg_credentials[attribute] = params.get(attribute, None)
|
||||
|
||||
if arg_credentials['cli_default_profile']:
|
||||
self.log('Retrieving credentials from Azure CLI current profile')
|
||||
return self._get_azure_cli_profile()
|
||||
auth_source = params.get('auth_source', None)
|
||||
if not auth_source:
|
||||
auth_source = os.environ.get('ANSIBLE_AZURE_AUTH_SOURCE', 'auto')
|
||||
|
||||
if auth_source == 'cli':
|
||||
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`")
|
||||
try:
|
||||
self.log('Retrieving credentials from Azure CLI profile')
|
||||
cli_credentials = self._get_azure_cli_credentials()
|
||||
return cli_credentials
|
||||
except CLIError as err:
|
||||
self.fail("Azure CLI profile cannot be loaded - {0}".format(err))
|
||||
|
||||
if auth_source == 'env':
|
||||
self.log('Retrieving credentials from environment')
|
||||
env_credentials = self._get_env_credentials()
|
||||
return env_credentials
|
||||
|
||||
if auth_source == 'credential_file':
|
||||
self.log("Retrieving credentials from credential file")
|
||||
profile = params.get('profile', 'default')
|
||||
default_credentials = self._get_profile(profile)
|
||||
return default_credentials
|
||||
|
||||
# auto, precedence: module parameters -> environment variables -> default profile in ~/.azure/credentials
|
||||
# try module params
|
||||
if arg_credentials['profile'] is not None:
|
||||
self.log('Retrieving credentials with profile parameter.')
|
||||
|
@ -523,6 +549,14 @@ class AzureRMModuleBase(object):
|
|||
self.log('Retrieved default profile credentials from ~/.azure/credentials.')
|
||||
return default_credentials
|
||||
|
||||
try:
|
||||
if HAS_AZURE_CLI_CORE:
|
||||
self.log('Retrieving credentials from AzureCLI profile')
|
||||
cli_credentials = self._get_azure_cli_credentials()
|
||||
return cli_credentials
|
||||
except CLIError as ce:
|
||||
self.log('Error getting AzureCLI profile credentials - {0}'.format(ce))
|
||||
|
||||
return None
|
||||
|
||||
def serialize_obj(self, obj, class_name, enum_modules=None):
|
||||
|
|
|
@ -76,6 +76,20 @@ options:
|
|||
choices: [validate, ignore]
|
||||
default: null
|
||||
version_added: 2.5
|
||||
auth_source:
|
||||
description:
|
||||
- Controls the source of the credentials to use for authentication.
|
||||
- C(auto) will follow the default precedence of module parameters -> environment variables -> default profile in credential file
|
||||
C(~/.azure/credentials).
|
||||
- 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.
|
||||
choices:
|
||||
- auto
|
||||
- cli
|
||||
- credential_file
|
||||
- env
|
||||
default: auto
|
||||
version_added: 2.5
|
||||
requirements:
|
||||
- "python >= 2.7"
|
||||
- "azure >= 2.0.0"
|
||||
|
|
Loading…
Reference in a new issue