diff --git a/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py
new file mode 100644
index 00000000000..29dd53f7cd0
--- /dev/null
+++ b/lib/ansible/modules/cloud/azure/azure_rm_keyvaultkey.py
@@ -0,0 +1,278 @@
+#!/usr/bin/python
+# Copyright: Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+ANSIBLE_METADATA = {'metadata_version': '1.1',
+                    'status': ['preview'],
+                    'supported_by': 'community'}
+
+
+DOCUMENTATION = '''
+---
+module: azure_rm_keyvaultkey
+version_added: 2.5
+short_description: Use Azure KeyVault keys.
+description:
+    - Create or delete a key within a given keyvault. By using Key Vault, you can encrypt
+      keys and secrets (such as authentication keys, storage account keys, data encryption keys, .PFX files, and passwords).
+options:
+    keyvault_uri:
+            description:
+                - URI of the keyvault endpoint.
+            required: true
+    key_name:
+        description:
+            - Name of the keyvault key.
+        required: true
+    byok_file:
+        description:
+            - BYOK file.
+    pem_file:
+        description:
+            - PEM file.
+    pem_password:
+        description:
+            - PEM password.
+    state:
+        description:
+            - Assert the state of the key. Use 'present' to create a key and
+              'absent' to delete a key.
+        required: false
+        default: present
+        choices:
+            - absent
+            - present
+
+extends_documentation_fragment:
+    - azure
+    - azure_tags
+
+author:
+    - "Ian Philpot (@tripdubroot)"
+
+'''
+
+EXAMPLES = '''
+    - name: Create a key
+      azure_rm_keyvaultkey:
+        key_name: MyKey
+        keyvault_uri: https://contoso.vault.azure.net/
+
+    - name: Delete a key
+      azure_rm_keyvaultkey:
+        key_name: MyKey
+        keyvault_uri: https://contoso.vault.azure.net/
+        state: absent
+'''
+
+RETURN = '''
+state:
+    description: Current state of the key.
+    returned: success
+    type: complex
+    contains:
+        key_id:
+          description: key resource path.
+          type: str
+          example: https://contoso.vault.azure.net/keys/hello/e924f053839f4431b35bc54393f98423
+'''
+
+from ansible.module_utils.azure_rm_common import AzureRMModuleBase
+
+try:
+    import re
+    import codecs
+    from azure.keyvault import KeyVaultClient, KeyVaultId
+    from azure.keyvault.models import KeyAttributes, JsonWebKey
+    from azure.common.credentials import ServicePrincipalCredentials
+    from azure.keyvault.models.key_vault_error import KeyVaultErrorException
+    from OpenSSL import crypto
+except ImportError:
+    # This is handled in azure_rm_common
+    pass
+
+
+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)
+
+
+def main():
+    AzureRMKeyVaultKey()
+
+if __name__ == '__main__':
+    main()
diff --git a/test/integration/targets/azure_rm_keyvaultkey/aliases b/test/integration/targets/azure_rm_keyvaultkey/aliases
new file mode 100644
index 00000000000..d6ff84111cd
--- /dev/null
+++ b/test/integration/targets/azure_rm_keyvaultkey/aliases
@@ -0,0 +1,3 @@
+cloud/azure
+posix/ci/cloud/azure
+destructive
diff --git a/test/integration/targets/azure_rm_keyvaultkey/meta/main.yml b/test/integration/targets/azure_rm_keyvaultkey/meta/main.yml
new file mode 100644
index 00000000000..95e1952f989
--- /dev/null
+++ b/test/integration/targets/azure_rm_keyvaultkey/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+  - setup_azure
diff --git a/test/integration/targets/azure_rm_keyvaultkey/tasks/main.yml b/test/integration/targets/azure_rm_keyvaultkey/tasks/main.yml
new file mode 100644
index 00000000000..b617c922ab7
--- /dev/null
+++ b/test/integration/targets/azure_rm_keyvaultkey/tasks/main.yml
@@ -0,0 +1,69 @@
+- name: Prepare random number
+  set_fact:
+    rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}"
+  run_once: yes
+
+- name: Create instance of Key Vault
+  azure_rm_keyvault:
+    resource_group: "{{ resource_group }}"
+    vault_name: "vault{{ rpfx }}"
+    enabled_for_deployment: yes
+    vault_tenant: "{{ azure_tenant }}"
+    sku:
+      name: standard
+      family: A
+    access_policies:
+      - tenant_id: "{{ azure_tenant }}"
+        object_id: 97567bfa-cf13-4217-8fa3-cc56bc1867fe
+        keys:
+          - get
+          - list
+          - update
+          - create
+          - import
+          - delete
+          - recover
+          - backup
+          - restore
+        secrets:
+          - get
+          - list
+          - set
+          - delete
+          - recover
+          - backup
+          - restore
+  register: output
+
+- name: create a kevyault key
+  block:
+    - azure_rm_keyvaultkey:
+        keyvault_uri: https://vault{{ rpfx }}.vault.azure.net
+        key_name: testkey
+        tags:
+          testing: test
+          delete: on-exit
+      register: output
+    - assert:
+        that: output.changed
+  rescue:
+    - azure_rm_keyvaultkey:
+        keyvault_uri: https://vault{{ rpfx }}.vault.azure.net
+        state: absent
+        key_name: testkey
+
+- name: delete a kevyault key
+  azure_rm_keyvaultkey:
+    keyvault_uri: https://vault{{ rpfx }}.vault.azure.net
+    state: absent
+    key_name: testkey
+  register: output
+
+- assert:
+    that: output.changed
+
+- name: Delete instance of Key Vault
+  azure_rm_keyvault:
+    resource_group: "{{ resource_group }}"
+    vault_name: "vault{{ rpfx }}"
+    state: absent