From 861b710c735ae1a5bf854c68699ecdfa19a09a75 Mon Sep 17 00:00:00 2001 From: Yunge Zhu <37337818+yungezz@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:26:34 +0800 Subject: [PATCH] fix keyvault auth in msi auth (#53100) --- .../cloud/azure/azure_rm_keyvaultkey.py | 50 +++++++++++------- .../cloud/azure/azure_rm_keyvaultsecret.py | 52 ++++++++++++------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py index 21e78fd484..e223c2164e 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py @@ -89,6 +89,7 @@ try: from azure.keyvault.models import KeyAttributes, JsonWebKey from azure.common.credentials import ServicePrincipalCredentials from azure.keyvault.models.key_vault_error import KeyVaultErrorException + from msrestazure.azure_active_directory import MSIAuthentication from OpenSSL import crypto except ImportError: # This is handled in azure_rm_common @@ -137,25 +138,7 @@ class AzureRMKeyVaultKey(AzureRMModuleBase): setattr(self, key, kwargs[key]) # Create KeyVaultClient - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials['secret'] is None: - self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://vault.azure.net") - - token = authcredential.token - return token['token_type'], token['access_token'] - - self.client = KeyVaultClient(KeyVaultAuthentication(auth_callback)) + self.client = self.get_keyvault_client() results = dict() changed = False @@ -195,6 +178,35 @@ class AzureRMKeyVaultKey(AzureRMModuleBase): return self.results + def get_keyvault_client(self): + try: + self.log("Get KeyVaultClient from MSI") + credentials = MSIAuthentication(resource='https://vault.azure.net') + return KeyVaultClient(credentials) + except Exception: + self.log("Get KeyVaultClient from service principal") + + # Create KeyVault Client using KeyVault auth class and auth_callback + def auth_callback(server, resource, scope): + if self.credentials['client_id'] is None or self.credentials['secret'] is None: + self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') + + tenant = self.credentials.get('tenant') + if not self.credentials['tenant']: + tenant = "common" + + authcredential = ServicePrincipalCredentials( + client_id=self.credentials['client_id'], + secret=self.credentials['secret'], + tenant=tenant, + cloud_environment=self._cloud_environment, + resource="https://vault.azure.net") + + token = authcredential.token + return token['token_type'], token['access_token'] + + return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + def get_key(self, name, version=''): ''' Gets an existing key ''' key_bundle = self.client.get_key(self.keyvault_uri, name, version) diff --git a/lib/ansible/modules/cloud/azure/azure_rm_keyvaultsecret.py b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultsecret.py index 0e43896e7f..0f790e453f 100644 --- a/lib/ansible/modules/cloud/azure/azure_rm_keyvaultsecret.py +++ b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultsecret.py @@ -84,6 +84,7 @@ try: from azure.keyvault import KeyVaultClient, KeyVaultAuthentication, KeyVaultId from azure.common.credentials import ServicePrincipalCredentials from azure.keyvault.models.key_vault_error import KeyVaultErrorException + from msrestazure.azure_active_directory import MSIAuthentication except ImportError: # This is handled in azure_rm_common pass @@ -128,26 +129,8 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): for key in list(self.module_arg_spec.keys()) + ['tags']: setattr(self, key, kwargs[key]) - # Create KeyVault Client using KeyVault auth class and auth_callback - def auth_callback(server, resource, scope): - if self.credentials['client_id'] is None or self.credentials['secret'] is None: - self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') - - tenant = self.credentials.get('tenant') - if not self.credentials['tenant']: - tenant = "common" - - authcredential = ServicePrincipalCredentials( - client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=tenant, - cloud_environment=self._cloud_environment, - resource="https://vault.azure.net") - - token = authcredential.token - return token['token_type'], token['access_token'] - - self.client = KeyVaultClient(KeyVaultAuthentication(auth_callback)) + # Create KeyVault Client + self.client = self.get_keyvault_client() results = dict() changed = False @@ -186,6 +169,35 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): return self.results + def get_keyvault_client(self): + try: + self.log("Get KeyVaultClient from MSI") + credentials = MSIAuthentication(resource='https://vault.azure.net') + return KeyVaultClient(credentials) + except Exception: + self.log("Get KeyVaultClient from service principal") + + # Create KeyVault Client using KeyVault auth class and auth_callback + def auth_callback(server, resource, scope): + if self.credentials['client_id'] is None or self.credentials['secret'] is None: + self.fail('Please specify client_id, secret and tenant to access azure Key Vault.') + + tenant = self.credentials.get('tenant') + if not self.credentials['tenant']: + tenant = "common" + + authcredential = ServicePrincipalCredentials( + client_id=self.credentials['client_id'], + secret=self.credentials['secret'], + tenant=tenant, + cloud_environment=self._cloud_environment, + resource="https://vault.azure.net") + + token = authcredential.token + return token['token_type'], token['access_token'] + + return KeyVaultClient(KeyVaultAuthentication(auth_callback)) + def get_secret(self, name, version=''): ''' Gets an existing secret ''' secret_bundle = self.client.get_secret(self.keyvault_uri, name, version)