diff --git a/README-automountkey.md b/README-automountkey.md
new file mode 100644
index 0000000000000000000000000000000000000000..a4c1ab6956b6fad684616aa55a6307313646d431
--- /dev/null
+++ b/README-automountkey.md
@@ -0,0 +1,104 @@
+Automountkey module
+=====================
+
+Description
+-----------
+
+The automountkey module allows the addition and removal of keys within an automount map. 
+
+It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
+
+
+Features
+--------
+* Automount key management
+
+Supported FreeIPA Versions
+--------------------------
+
+FreeIPA versions 4.4.0 and up are supported by the ipaautomountkey module.
+
+Requirements
+------------
+**Controller**
+* Ansible version: 2.8+
+
+**Node**
+* Supported FreeIPA version (see above)
+
+
+Usage
+=====
+
+Example inventory file
+
+```ini
+[ipaserver]
+ipaserver.test.local
+```
+
+
+Example playbook to ensure presence of an automount map:
+
+```yaml
+---
+- name: Playbook to add an automount map
+  hosts: ipaserver
+  become: true
+
+  tasks:
+  - name: create key TestKey
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      location: TestLocation
+      mapname: TestMap
+      key: TestKey
+      info: 192.168.122.1:/exports
+      state: present
+
+  - name: ensure key TestKey is absent
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      location: TestLocation
+      mapname: TestMap
+      key: TestKey
+      state: absent
+```
+
+Example playbook to rename an automount map:
+
+```yaml
+---
+- name: Playbook to add an automount map
+  - name: ensure key TestKey has been renamed to NewKeyName
+    ipaautomountkey:
+      ipaadmin_password: password01
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      newname: NewKeyName
+      state: rename
+```
+
+
+Variables
+=========
+
+ipaautomountkey
+-------
+
+Variable | Description | Required
+-------- | ----------- | --------
+`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
+`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
+`location` \| `automountlocationcn` \| `automountlocation` | Location name. | yes 
+`mapname` \|  `map` \| `automountmapname` \| `automountmap` | Map the key belongs to | yes 
+`key` \| `name` \| `automountkey` | Automount key to manage | yes 
+`newkey` \| newname` \| `newautomountkey` | the name to change the key to if state is `rename` | yes when state is `rename`
+`info` \| `information` \| `automountinformation` | Mount information for the key | yes when state is `present`
+`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no
+
+Authors
+=======
+
+Chris Procter
diff --git a/playbooks/automount/.automount-map-present.yml.swp b/playbooks/automount/.automount-map-present.yml.swp
new file mode 100644
index 0000000000000000000000000000000000000000..1a9bbc91a11e1d02cb72378a07472de6debf2cc1
Binary files /dev/null and b/playbooks/automount/.automount-map-present.yml.swp differ
diff --git a/plugins/modules/ipaautomountkey.py b/plugins/modules/ipaautomountkey.py
new file mode 100644
index 0000000000000000000000000000000000000000..772ff2ed64886d4a594ecb250d53f4c64b7666f3
--- /dev/null
+++ b/plugins/modules/ipaautomountkey.py
@@ -0,0 +1,217 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Authors:
+#   Chris Procter <cprocter@redhat.com>
+#
+# Copyright (C) 2021 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ANSIBLE_METADATA = {
+    "metadata_version": "1.0",
+    "supported_by": "community",
+    "status": ["preview"],
+}
+
+
+DOCUMENTATION = '''
+---
+module: ipaautomountkey
+author: chris procter
+short_description: Manage FreeIPA autommount map
+description:
+- Add, delete, and modify an IPA automount map
+options:
+  ipaadmin_principal:
+    description: The admin principal
+    default: admin
+  ipaadmin_password:
+    description: The admin password
+    required: False
+  location:
+    description: automount location map is in
+    required: True
+    choices: ["automountlocationcn", "automountlocation"]
+  mapname:
+    description: automount map to be managed
+    choices: ["map", "automountmapname", "automountmap"]
+    required: True
+  key:
+    description: automount key to be managed
+    required: True
+    choices: ["name", "automountkey"]
+  newkey:
+    description: key to change to if state=rename
+    required: True
+    choices: ["newname", "newautomountkey"]
+  info:
+    description: Mount information for the key
+    required: True
+    choices: ["information", "newinfo", "automountinformation"]
+  state:
+    description: State to ensure
+    required: False
+    default: present
+    choices: ["present", "absent", "rename"]
+'''
+
+EXAMPLES = '''
+  - name: create key TestKey
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      locationcn: TestLocation
+      mapname: TestMap
+      key: TestKey
+      info: 192.168.122.1:/exports
+      state: present
+
+  - name: ensure key TestKey is absent
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      location: TestLocation
+      mapname: TestMap
+      key: TestKey
+      state: absent
+'''
+
+RETURN = '''
+'''
+
+from ansible.module_utils.ansible_freeipa_module import (
+    FreeIPABaseModule, ipalib_errors
+)
+
+
+class AutomountKey(FreeIPABaseModule):
+
+    ipa_param_mapping = {
+        'automountkey': "key",
+        'automountmapautomountmapname': "mapname",
+    }
+
+    def get_key(self, location, mapname, keyname):
+        resp = dict()
+        try:
+            resp = self.api_command("automountkey_show",
+                                    location,
+                                    {"automountmapautomountmapname": mapname,
+                                     "automountkey": keyname})
+        except ipalib_errors.NotFound:
+            pass
+
+        return resp.get("result", None)
+
+    def check_ipa_params(self):
+        if not self.ipa_params.info and self.ipa_params.state == "present":
+            self.fail_json(msg="Value required for argument 'info'")
+
+        if self.ipa_params.state == "rename" and \
+           self.ipa_params.newname is None:
+            self.fail_json(msg="newname is required if state = 'rename'")
+
+    def define_ipa_commands(self):
+        args = self.get_ipa_command_args()
+        key = self.get_key(self.ipa_params.location,
+                           self.ipa_params.mapname,
+                           self.ipa_params.key)
+
+        if self.ipa_params.state == "present":
+            if key is None:
+                # does not exist and is wanted
+                args["automountinformation"] = self.ipa_params.info
+                self.add_ipa_command(
+                    "automountkey_add",
+                    name=self.ipa_params.location,
+                    args=args
+                )
+            elif key is not None:
+                # exists and is wanted, check for changes
+                if self.ipa_params.info != \
+                        key.get('automountinformation', [None])[0]:
+                    args["newautomountinformation"] = self.ipa_params.info
+                    self.add_ipa_command(
+                        "automountkey_mod",
+                        name=self.ipa_params.location,
+                        args=args
+                    )
+        elif self.ipa_params.state == "rename":
+            if key is not None:
+                newkey = self.get_key(self.ipa_params.location,
+                                      self.ipa_params.mapname,
+                                      self.ipa_params.newname)
+
+                args["rename"] = self.ipa_params.newname
+                if newkey is None:
+                    self.add_ipa_command(
+                        "automountkey_mod",
+                        name=self.ipa_params.location,
+                        args=args
+                    )
+        else:
+            # if key exists and self.ipa_params.state == "absent":
+            if key is not None:
+                self.add_ipa_command(
+                    "automountkey_del",
+                    name=self.ipa_params.location,
+                    args=args
+                )
+
+
+def main():
+    ipa_module = AutomountKey(
+        argument_spec=dict(
+            ipaadmin_principal=dict(type="str",
+                                    default="admin"
+                                    ),
+            ipaadmin_password=dict(type="str",
+                                   required=False,
+                                   no_log=True
+                                   ),
+            state=dict(type='str',
+                       default='present',
+                       choices=['present', 'absent', 'rename']
+                       ),
+            location=dict(type="str",
+                          aliases=["automountlocationcn", "automountlocation"],
+                          default=None,
+                          required=True
+                          ),
+            newname=dict(type="str",
+                         aliases=["newkey", "new_name",
+                                  "new_key", "newautomountkey"],
+                         default=None,
+                         required=False
+                         ),
+            mapname=dict(type="str",
+                         aliases=["map", "automountmapname", "automountmap"],
+                         default=None,
+                         required=True
+                         ),
+            key=dict(type="str",
+                     required=True,
+                     aliases=["name", "automountkey"]
+                     ),
+            info=dict(type="str",
+                      aliases=["information", "newinfo",
+                               "automountinformation"]
+                      ),
+        ),
+    )
+    ipa_module.ipa_run()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/automount/test_automountkey.yml b/tests/automount/test_automountkey.yml
new file mode 100644
index 0000000000000000000000000000000000000000..19c8922a74c22a6ecdea958c61ceab3ec319091e
--- /dev/null
+++ b/tests/automount/test_automountkey.yml
@@ -0,0 +1,180 @@
+---
+- name: Test automountmap
+  hosts: ipaserver
+  become: true
+  gather_facts: false
+
+  tasks:
+  - name: ensure location TestLocation is absent
+    ipaautomountlocation:
+      ipaadmin_password: SomeADMINpassword
+      name: TestLocation
+      state: absent
+
+#  - name: ensure map TestMap is absent
+ #   ipaautomountmap:
+ #     ipaadmin_password: SomeADMINpassword
+ #     name: TestMap
+ #     location: TestLocation
+ #     state: absent
+#
+#  - name: ensure key TestKey is absent
+#    ipaautomountkey:
+#      ipaadmin_password: SomeADMINpassword
+#      automountlocationcn: TestLocation
+#      automountmapname: TestMap
+#      automountkey: TestKey
+#      state: absent
+
+  - name: create location TestLocation
+    ipaautomountlocation:
+      ipaadmin_password: SomeADMINpassword
+      name: TestLocation
+      state: present
+
+  - name: create map TestMap 
+    ipaautomountmap:
+      ipaadmin_password: SomeADMINpassword
+      name: TestMap
+      location: TestLocation
+      desc: "this is a test map that should be deleted by the test"
+
+### test the key creation, and modification
+  - name: ensure key TestKey is present
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/exports
+      state: present
+    register: result
+    failed_when: result.failed or not result.changed
+
+  - name: ensure key TestKey is present again
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/exports
+      state: present
+    register: result
+    failed_when: result.failed or result.changed
+
+## modify the key
+  - name: ensure key TestKey information has been updated
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/nfsshare
+      state: present
+    register: result
+    failed_when: result.failed or not result.changed
+
+  - name: ensure key TestKey information has been updated again
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/nfsshare
+      state: present
+    register: result
+    failed_when: result.failed or result.changed
+
+## modify the name
+  - name: ensure key TestKey has been renamed to NewKeyName
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/nfsshare
+      newname: NewKeyName
+      state: rename
+    register: result
+    failed_when: result.failed or not result.changed
+
+  - name: ensure key TestKey does not exist
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: NewKeyName
+      automountinformation: 192.168.122.1:/nfsshare
+      state: present
+    register: result
+    failed_when: result.failed or result.changed
+
+  - name: ensure key NewKeyName does exist
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: NewKeyName
+      automountinformation: 192.168.122.1:/nfsshare
+      state: present
+    register: result
+    failed_when: result.failed or result.changed
+
+  - name: ensure key TestKey has been renamed to NewKeyName again
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/nfsshare
+      newname: NewKeyName
+      state: rename
+    register: result
+    failed_when: result.failed or result.changed
+
+  - name: ensure failure when state=present and newname is not set
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: TestKey
+      automountinformation: 192.168.122.1:/nfsshare
+      state: rename
+    register: result
+    failed_when: not result.failed
+
+
+### cleanup after the tests
+  - name: ensure key NewKeyName is absent
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: NewKeyName
+      state: absent
+    register: result
+    failed_when: result.failed or not result.changed
+
+  - name: ensure key TestKey is absent again
+    ipaautomountkey:
+      ipaadmin_password: SomeADMINpassword
+      automountlocationcn: TestLocation
+      automountmapname: TestMap
+      automountkey: NewKeyName
+      state: absent
+    register: result
+    failed_when: result.failed or result.changed
+
+  - name: ensure map TestMap is removed
+    ipaautomountmap:
+      ipaadmin_password: SomeADMINpassword
+      name: TestMap
+      location: TestLocation
+      state: absent
+
+  - name: ensure location TestLocation is removed
+    ipaautomountlocation:
+      ipaadmin_password: SomeADMINpassword
+      name: TestLocation
+      state: absent
+