def _get_keyvault_key_url(keyvault_name, key_name): from azure.cli.core._profile import Profile def get_token(server, resource, scope): # pylint: disable=unused-argument return Profile().get_login_credentials(resource)[0]._token_retriever() # pylint: disable=protected-access from azure.keyvault import KeyVaultClient, KeyVaultAuthentication client = KeyVaultClient(KeyVaultAuthentication(get_token)) result = client.get_key(_get_key_vault_base_url(keyvault_name), key_name, '') return result.key.kid # pylint: disable=no-member
def run_example(): """MSI Authentication example.""" # # Create System Assigned MSI Authentication # credentials = MSIAuthentication() client = KeyVaultClient(credentials) key_bundle = client.get_key(vault_url, key_name, key_version) json_key = key_bundle.key print json_key
class AzureRMKeyVaultKey(AzureRMModuleBase): ''' Module that creates or deletes keys in Azure KeyVault ''' def __init__(self): self.module_arg_spec = dict( key_name=dict(type='str', required=True), keyvault_uri=dict(type='str', required=True), pem_file=dict(type='str'), pem_password=dict(type='str'), byok_file=dict(type='str'), state=dict(type='str', default='present', choices=['present', 'absent']) ) self.results = dict( changed=False, state=dict() ) self.key_name = None self.keyvault_uri = None self.pem_file = None self.pem_password = None self.state = None self.client = None self.tags = None required_if = [ ('pem_password', 'present', ['pem_file']) ] super(AzureRMKeyVaultKey, self).__init__(self.module_arg_spec, supports_check_mode=True, required_if=required_if, supports_tags=True) def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()) + ['tags']: 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, resource="https://vault.azure.net") token = authcredential.token return token['token_type'], token['access_token'] self.client = KeyVaultClient(KeyVaultAuthentication(auth_callback)) results = dict() changed = False try: results['key_id'] = self.get_key(self.key_name) # Key exists and will be deleted if self.state == 'absent': changed = True except KeyVaultErrorException: # Key doesn't exist if self.state == 'present': changed = True self.results['changed'] = changed self.results['state'] = results if not self.check_mode: # Create key if self.state == 'present' and changed: results['key_id'] = self.create_key(self.key_name, self.tags) self.results['state'] = results self.results['state']['status'] = 'Created' # Delete key elif self.state == 'absent' and changed: results['key_id'] = self.delete_key(self.key_name) self.results['state'] = results self.results['state']['status'] = 'Deleted' else: if self.state == 'present' and changed: self.results['state']['status'] = 'Created' elif self.state == 'absent' and changed: self.results['state']['status'] = 'Deleted' return self.results def get_key(self, name, version=''): ''' Gets an existing key ''' key_bundle = self.client.get_key(self.keyvault_uri, name, version) if key_bundle: key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) return key_id.id def create_key(self, name, tags, kty='RSA'): ''' Creates a key ''' key_bundle = self.client.create_key(vault_base_url=self.keyvault_uri, key_name=name, kty=kty, tags=tags) key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) return key_id.id def delete_key(self, name): ''' Deletes a key ''' deleted_key = self.client.delete_key(self.keyvault_uri, name) key_id = KeyVaultId.parse_key_id(deleted_key.key.kid) return key_id.id def import_key(self, key_name, destination=None, key_ops=None, disabled=False, expires=None, not_before=None, tags=None, pem_file=None, pem_password=None, byok_file=None): """ Import a private key. Supports importing base64 encoded private keys from PEM files. Supports importing BYOK keys into HSM for premium KeyVaults. """ def _to_bytes(hex_string): # zero pads and decodes a hex string if len(hex_string) % 2: hex_string = '{0}'.format(hex_string) return codecs.decode(hex_string, 'hex_codec') def _set_rsa_parameters(dest, src): # map OpenSSL parameter names to JsonWebKey property names conversion_dict = { 'modulus': 'n', 'publicExponent': 'e', 'privateExponent': 'd', 'prime1': 'p', 'prime2': 'q', 'exponent1': 'dp', 'exponent2': 'dq', 'coefficient': 'qi' } # regex: looks for matches that fit the following patterns: # integerPattern: 65537 (0x10001) # hexPattern: # 00:a0:91:4d:00:23:4a:c6:83:b2:1b:4c:15:d5:be: # d8:87:bd:c9:59:c2:e5:7a:f5:4a:e7:34:e8:f0:07: # The desired match should always be the first component of the match regex = re.compile(r'([^:\s]*(:[^\:)]+\))|([^:\s]*(:\s*[0-9A-Fa-f]{2})+))') # regex2: extracts the hex string from a format like: 65537 (0x10001) regex2 = re.compile(r'(?<=\(0x{1})([0-9A-Fa-f]*)(?=\))') key_params = crypto.dump_privatekey(crypto.FILETYPE_TEXT, src).decode('utf-8') for match in regex.findall(key_params): comps = match[0].split(':', 1) name = conversion_dict.get(comps[0], None) if name: value = comps[1].replace(' ', '').replace('\n', '').replace(':', '') try: value = _to_bytes(value) except Exception: # pylint:disable=broad-except # if decoding fails it is because of an integer pattern. Extract the hex # string and retry value = _to_bytes(regex2.findall(value)[0]) setattr(dest, name, value) key_attrs = KeyAttributes(not disabled, not_before, expires) key_obj = JsonWebKey(key_ops=key_ops) if pem_file: key_obj.kty = 'RSA' with open(pem_file, 'r') as f: pem_data = f.read() # load private key and prompt for password if encrypted try: pem_password = str(pem_password).encode() if pem_password else None # despite documentation saying password should be a string, it needs to actually # be UTF-8 encoded bytes pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pem_data, pem_password) except crypto.Error: pass # wrong password except TypeError: pass # no pass provided _set_rsa_parameters(key_obj, pkey) elif byok_file: with open(byok_file, 'rb') as f: byok_data = f.read() key_obj.kty = 'RSA-HSM' key_obj.t = byok_data return self.client.import_key( self.keyvault_uri, key_name, key_obj, destination == 'hsm', key_attrs, tags)
############################################################### from azure.keyvault import KeyVaultClient, KeyVaultAuthentication from azure.common.credentials import ServicePrincipalCredentials credentials = ServicePrincipalCredentials( client_id='YourClientAdd', secret='YourSecret', tenant='domain.onmicrosoft.com', ) VAULT_URL = 'https://YourKeyvaultNAME.vault.azure.net' SECRET_ID = 'mysecret' client = KeyVaultClient(credentials) # VAULT_URL must be in the format 'https://<vaultname>.vault.azure.net' # SECRET_VERSION is required, and can be obtained with the KeyVaultClient.get_secret_versions(self, vault_url, secret_id) API key_bundle = client.get_key(VAULT_URL, 'key', 'e371b887e1f54708a947cc8570272543') key = key_bundle.key secret_bundle = client.get_secret(VAULT_URL, SECRET_ID, '90cdeb79bc494b77920ed2bbdba8139e') #Create a Secret my_secret = client.set_secret(VAULT_URL, "secretfrompython2", "pythonvalue2") #Create a Key key2 = client.create_key(VAULT_URL, "key2", "RSA") versions = client.get_key_versions(VAULT_URL, SECRET_ID) #Delete a Key delete_key(vault_base_url, key_name, custom_headers=None, raw=False, **operation_config) #client.delete_key(VAULT_URL,"key2") print(my_secret) print(secret_bundle) print(key) print(key2)
class AESKeyWrapper: """ Wrapper for key wrapping functions. Key is wrapped localy with public key retrieved from Azure KeyVault. Uses Azure KeyVault API to unwrap the key. """ def __init__(self, vault, client_id, secret, tenant, key_name, key_version): """ Wrapper constructor. :param str vault: Azure KeyVault url. :param str client_id: Azure Client Id. :param str secret: Azure Client secret. :param str tenant: Azure tenant id. :param str key_name: Azure KeyVault key name. :param str key_version: Azure KeyVault key version. """ self._key_name = key_name self._key_version = key_version self._vault = vault self._client_id = client_id self._secret = secret self._tenant = tenant self._credentials = ServicePrincipalCredentials( client_id=self._client_id, secret=self._secret, tenant=self._tenant) self.kvclient = KeyVaultClient(self._credentials) def wrap_aes_key_local(self, aes_key, public_key): """ Wraps AES key locally. Uses RSA-OAEP algorithm to wrap provided key. :param str aes_key: unencrypted AES key. :param str public_key: public part of RSA key. :return: String with encrypted AES key. """ int_n = self._bytes_to_int(public_key.n) int_e = self._bytes_to_int(public_key.e) public_numbers = RSAPublicNumbers(int_e, int_n) public_key = public_numbers.public_key(default_backend()) wrapped_key = public_key.encrypt( aes_key, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None)) return wrapped_key def unwrap_aes_key(self, wrapped_key): """ Unwraps AES key with Azure KeyVault. Uses RSA-OAEP algorithm to unwrap provided key. :param str wrapped_key: encrypted AES key. :return: String with unencrypted AES key. """ return self.kvclient.unwrap_key(self._vault, self._key_name, self._key_version, 'RSA-OAEP', wrapped_key).result def get_public_key(self): """ Retrieve public key from Azure KeyVault. :return: JsonWebKey with public RSA key. """ key_bundle = self.kvclient.get_key(self._vault, self._key_name, self._key_version) return key_bundle.key def _bytes_to_int(self, bytes): """ Helper function to convert bytes array to int. """ result = 0 for b in bytes: result = result * 256 + ord(b) return result
config = { 'kv_name_domain': 'testhostname', # this name to be used for the vault domain 'node_addr': 'http://127.0.0.1:8732', 'keys': {}, # to be auto-populated 'bakerid': socket.getfqdn() + '_' + str(uuid4()) } info("Getting public keys from HSM") kvurl = 'https://' + config['kv_name_domain'] + '.vault.azure.net' kvclient = KeyVaultClient( MSIAuthentication(resource='https://vault.azure.net')) keys = kvclient.get_keys(kvurl) for key in keys: keyname = key.kid.split('/') keydat = kvclient.get_key(kvurl, keyname[-1], '').key parity = bytes([2]) if int.from_bytes(keydat.y, 'big') % 2 == 1: parity = bytes([3]) shabytes = sha256(sha256(P2PK_MAGIC + parity + keydat.x).digest()).digest()[:4] public_key = b58encode(P2PK_MAGIC + parity + keydat.x + shabytes).decode() blake2bhash = blake2b(parity + keydat.x, digest_size=20).digest() shabytes = sha256(sha256(P2HASH_MAGIC + blake2bhash).digest()).digest()[:4] pkhash = b58encode(P2HASH_MAGIC + blake2bhash + shabytes).decode() config['keys'].update( {pkhash: { 'kv_keyname': keyname[-1], 'public_key': public_key
class AzureRMKeyVaultKey(AzureRMModuleBase): ''' Module that creates or deletes keys in Azure KeyVault ''' def __init__(self): self.module_arg_spec = dict( key_name=dict(type='str', required=True), keyvault_uri=dict(type='str', required=True), pem_file=dict(type='str'), pem_password=dict(type='str'), byok_file=dict(type='str'), state=dict(type='str', default='present', choices=['present', 'absent']) ) self.results = dict( changed=False, state=dict() ) self.key_name = None self.keyvault_uri = None self.pem_file = None self.pem_password = None self.state = None self.client = None self.tags = None required_if = [ ('pem_password', 'present', ['pem_file']) ] super(AzureRMKeyVaultKey, self).__init__(self.module_arg_spec, supports_check_mode=True, required_if=required_if, supports_tags=True) def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()) + ['tags']: setattr(self, key, kwargs[key]) # Create KeyVaultClient self.client = KeyVaultClient(self.azure_credentials) results = dict() changed = False try: results['key_id'] = self.get_key(self.key_name) # Key exists and will be deleted if self.state == 'absent': changed = True except KeyVaultErrorException: # Key doesn't exist if self.state == 'present': changed = True self.results['changed'] = changed self.results['state'] = results if not self.check_mode: # Create key if self.state == 'present' and changed: results['key_id'] = self.create_key(self.key_name, self.tags) self.results['state'] = results self.results['state']['status'] = 'Created' # Delete key elif self.state == 'absent' and changed: results['key_id'] = self.delete_key(self.key_name) self.results['state'] = results self.results['state']['status'] = 'Deleted' else: if self.state == 'present' and changed: self.results['state']['status'] = 'Created' elif self.state == 'absent' and changed: self.results['state']['status'] = 'Deleted' return self.results def get_key(self, name, version=''): ''' Gets an existing key ''' key_bundle = self.client.get_key(self.keyvault_uri, name, version) if key_bundle: key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) return key_id.id def create_key(self, name, tags, kty='RSA'): ''' Creates a key ''' key_bundle = self.client.create_key(self.keyvault_uri, name, kty, tags=tags) key_id = KeyVaultId.parse_key_id(key_bundle.key.kid) return key_id.id def delete_key(self, name): ''' Deletes a key ''' deleted_key = self.client.delete_key(self.keyvault_uri, name) key_id = KeyVaultId.parse_key_id(deleted_key.key.kid) return key_id.id def import_key(self, key_name, destination=None, key_ops=None, disabled=False, expires=None, not_before=None, tags=None, pem_file=None, pem_password=None, byok_file=None): """ Import a private key. Supports importing base64 encoded private keys from PEM files. Supports importing BYOK keys into HSM for premium KeyVaults. """ def _to_bytes(hex_string): # zero pads and decodes a hex string if len(hex_string) % 2: hex_string = '{0}'.format(hex_string) return codecs.decode(hex_string, 'hex_codec') def _set_rsa_parameters(dest, src): # map OpenSSL parameter names to JsonWebKey property names conversion_dict = { 'modulus': 'n', 'publicExponent': 'e', 'privateExponent': 'd', 'prime1': 'p', 'prime2': 'q', 'exponent1': 'dp', 'exponent2': 'dq', 'coefficient': 'qi' } # regex: looks for matches that fit the following patterns: # integerPattern: 65537 (0x10001) # hexPattern: # 00:a0:91:4d:00:23:4a:c6:83:b2:1b:4c:15:d5:be: # d8:87:bd:c9:59:c2:e5:7a:f5:4a:e7:34:e8:f0:07: # The desired match should always be the first component of the match regex = re.compile(r'([^:\s]*(:[^\:)]+\))|([^:\s]*(:\s*[0-9A-Fa-f]{2})+))') # regex2: extracts the hex string from a format like: 65537 (0x10001) regex2 = re.compile(r'(?<=\(0x{1})([0-9A-Fa-f]*)(?=\))') key_params = crypto.dump_privatekey(crypto.FILETYPE_TEXT, src).decode('utf-8') for match in regex.findall(key_params): comps = match[0].split(':', 1) name = conversion_dict.get(comps[0], None) if name: value = comps[1].replace(' ', '').replace('\n', '').replace(':', '') try: value = _to_bytes(value) except Exception: # pylint:disable=broad-except # if decoding fails it is because of an integer pattern. Extract the hex # string and retry value = _to_bytes(regex2.findall(value)[0]) setattr(dest, name, value) key_attrs = KeyAttributes(not disabled, not_before, expires) key_obj = JsonWebKey(key_ops=key_ops) if pem_file: key_obj.kty = 'RSA' with open(pem_file, 'r') as f: pem_data = f.read() # load private key and prompt for password if encrypted try: pem_password = str(pem_password).encode() if pem_password else None # despite documentation saying password should be a string, it needs to actually # be UTF-8 encoded bytes pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pem_data, pem_password) except crypto.Error: pass # wrong password except TypeError: pass # no pass provided _set_rsa_parameters(key_obj, pkey) elif byok_file: with open(byok_file, 'rb') as f: byok_data = f.read() key_obj.kty = 'RSA-HSM' key_obj.t = byok_data return self.client.import_key( self.keyvault_uri, key_name, key_obj, destination == 'hsm', key_attrs, tags)
from azure.keyvault import KeyVaultClient, KeyVaultAuthentication from azure.common.credentials import ServicePrincipalCredentials credential = None def auth_callback(server, resource, scope): credentials = ServicePrincipalCredentials( client_id='952370c2-1f28-4256-b8c2-b241dca14159', secret='0n6rvVkXf9Q9uoFbKIvCdEGtGvlThri0bMQeA/4qgTk=', tenant='97df8ec2-114e-45ae-a59c-1f8c4ae0a138', resource="https://vault.azure.net") token = credentials.token return token['token_type'], token['access_token'] client = KeyVaultClient(KeyVaultAuthentication(auth_callback)) # key_bundle = client.get_key(vault_url, key_name, key_version) key_bundle = client.get_key('https://kv-dev-hk-peak-di-test.vault.azure.net/', 'mykey', 'e46409882744455c8a7ffee227777e09') secret_bundle = client.get_secret( 'https://kv-dev-hk-peak-di-test.vault.azure.net/', 'mysecret', 'fd65e2dada364f9b9211b0a26743bb05') print(secret_bundle.value) print(key_bundle.key)
#from azure.keyvault import K credentials = None def auth_callack(server, resource, scope): credentials = ServicePrincipalCredentials( client_id='73d64247-3c9e-493c-9ae3-3abae61ee024', secret='44QXoAKboDS5AIkXKmjUEsiu2AEneiHXFA6dfUB0i1U=', tenant='microsoft.onmicrosoft.com', resource=resource) token = credentials.token return token['token_type'], token['access_token'] client = KeyVaultClient(KeyVaultAuthentication(auth_callack)) vault_url = 'https://contosodemokeyvault.vault.azure.net/' key_name = 'contosodemokey1' key_version = '73cc4eca25b9409a83f57fdf8c55c82a' key_bundle = client.get_key(vault_url, key_name, key_version) json_key = key_bundle.key print(json_key)