allow cert validation to be disabled for Azure modules (#34906)

* `validate` or `ignore` values may be set by module, credential profile, or env. Module has highest precedence, followed by credential profile, then environment, and defaults to `validate` if not otherwise specified.
* fixes #33455
pull/34825/head
Matt Davis 7 years ago committed by GitHub
parent d72587084b
commit 9cf217a151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -404,3 +404,15 @@ You can execute the playbook with something like:
.. code-block:: bash .. code-block:: bash
$ ansible-playbook -i ./ansible/contrib/inventory/azure_rm.py test_azure_inventory.yml $ ansible-playbook -i ./ansible/contrib/inventory/azure_rm.py test_azure_inventory.yml
Disabling certificate validation on Azure endpoints
...................................................
When an HTTPS proxy is present, or when using Azure Stack, it may be necessary to disable certificate validation for
Azure endpoints in the Azure modules. This is not a recommended security practice, but may be necessary when the system
CA store cannot be altered to include the necessary CA certificate. Certificate validation can be controlled by setting
the "cert_validation_mode" value in a credential profile, via the "AZURE_CERT_VALIDATION_MODE" environment variable, or
by passing the "cert_validation_mode" argument to any Azure module. The default value is "validate"; setting the value
to "ignore" will prevent all certificate validation. The module argument takes precedence over a credential profile value,
which takes precedence over the environment value.

@ -44,6 +44,7 @@ AZURE_COMMON_ARGS = dict(
ad_user=dict(type='str', no_log=True), ad_user=dict(type='str', no_log=True),
password=dict(type='str', no_log=True), password=dict(type='str', no_log=True),
cloud_environment=dict(type='str'), cloud_environment=dict(type='str'),
cert_validation_mode=dict(type='str', choices=['validate', 'ignore'])
# debug=dict(type='bool', default=False), # debug=dict(type='bool', default=False),
) )
@ -57,6 +58,7 @@ AZURE_CREDENTIAL_ENV_MAPPING = dict(
ad_user='AZURE_AD_USER', ad_user='AZURE_AD_USER',
password='AZURE_PASSWORD', password='AZURE_PASSWORD',
cloud_environment='AZURE_CLOUD_ENVIRONMENT', cloud_environment='AZURE_CLOUD_ENVIRONMENT',
cert_validation_mode='AZURE_CERT_VALIDATION_MODE',
) )
AZURE_TAG_ARGS = dict( AZURE_TAG_ARGS = dict(
@ -255,6 +257,13 @@ class AzureRMModuleBase(object):
self.fail("Failed to get credentials. Either pass as parameters, set environment variables, " 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.") "or define a profile in ~/.azure/credentials or be logged using AzureCLI.")
# 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 \
os.environ.get('AZURE_CERT_VALIDATION_MODE') or 'validate'
if self._cert_validation_mode not in ['validate', 'ignore']:
self.fail('invalid cert_validation_mode: {0}'.format(self._cert_validation_mode))
# if cloud_environment specified, look up/build Cloud object # if cloud_environment specified, look up/build Cloud object
raw_cloud_env = self.credentials.get('cloud_environment') raw_cloud_env = self.credentials.get('cloud_environment')
if not raw_cloud_env: if not raw_cloud_env:
@ -286,7 +295,8 @@ class AzureRMModuleBase(object):
self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'], self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'],
secret=self.credentials['secret'], secret=self.credentials['secret'],
tenant=self.credentials['tenant'], tenant=self.credentials['tenant'],
cloud_environment=self._cloud_environment) 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: elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None:
tenant = self.credentials.get('tenant') tenant = self.credentials.get('tenant')
@ -296,7 +306,8 @@ class AzureRMModuleBase(object):
self.azure_credentials = UserPassCredentials(self.credentials['ad_user'], self.azure_credentials = UserPassCredentials(self.credentials['ad_user'],
self.credentials['password'], self.credentials['password'],
tenant=tenant, tenant=tenant,
cloud_environment=self._cloud_environment) cloud_environment=self._cloud_environment,
verify=self._cert_validation_mode == 'validate')
else: else:
self.fail("Failed to authenticate with provided credentials. Some attributes were missing. " self.fail("Failed to authenticate with provided credentials. Some attributes were missing. "
"Credentials must include client_id, secret and tenant or ad_user and password or " "Credentials must include client_id, secret and tenant or ad_user and password or "
@ -718,6 +729,10 @@ class AzureRMModuleBase(object):
return self.get_poller_result(poller) return self.get_poller_result(poller)
@staticmethod
def _validation_ignore_callback(session, global_config, local_config, **kwargs):
session.verify = False
def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None): def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None):
self.log('Getting management service client {0}'.format(client_type.__name__)) self.log('Getting management service client {0}'.format(client_type.__name__))
self.check_client_version(client_type) self.check_client_version(client_type)
@ -740,6 +755,9 @@ class AzureRMModuleBase(object):
if VSCODEEXT_USER_AGENT_KEY in os.environ: if VSCODEEXT_USER_AGENT_KEY in os.environ:
client.config.add_user_agent(os.environ[VSCODEEXT_USER_AGENT_KEY]) client.config.add_user_agent(os.environ[VSCODEEXT_USER_AGENT_KEY])
if self._cert_validation_mode == 'ignore':
client.config.session_configuration_callback = self._validation_ignore_callback
return client return client
@property @property

@ -67,6 +67,15 @@ options:
C(AzureUSGovernment)), or a metadata discovery endpoint URL (required for Azure Stack). Can also be set via credential file profile or C(AzureUSGovernment)), or a metadata discovery endpoint URL (required for Azure Stack). Can also be set via credential file profile or
the C(AZURE_CLOUD_ENVIRONMENT) environment variable. the C(AZURE_CLOUD_ENVIRONMENT) environment variable.
default: AzureCloud default: AzureCloud
version_added: 2.4
cert_validation_mode:
description:
- Controls the certificate validation behavior for Azure endpoints. By default, all modules will validate the server certificate, but
when an HTTPS proxy is in use, or against Azure Stack, it may be necessary to disable this behavior by passing C(ignore). Can also be
set via credential file profile or the C(AZURE_CERT_VALIDATION) environment variable.
choices: [validate, ignore]
default: null
version_added: 2.5
requirements: requirements:
- "python >= 2.7" - "python >= 2.7"
- "azure >= 2.0.0" - "azure >= 2.0.0"

Loading…
Cancel
Save