diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index e8d62e2800d5a57a973c16560ae5195b36be991e..7c60eb28497d1d1514532746c6bce426728ba303 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -45,6 +45,7 @@ else:
     import gssapi
     from datetime import datetime
     from pprint import pformat
+    from contextlib import contextmanager
 
     # ansible-freeipa requires locale to be C, IPA requires utf-8.
     os.environ["LANGUAGE"] = "C"
@@ -859,3 +860,109 @@ else:
                 self.check_ipa_params()
                 self.define_ipa_commands()
                 self._run_ipa_commands()
+
+    class IPAAnsibleModule(AnsibleModule):
+        """
+        IPA Ansible Module.
+
+        This class is an extended version of the Ansible Module that provides
+        IPA specific methods to simplify module generation.
+
+        Simple example:
+
+        from ansible.module_utils.ansible_freeipa_module import \
+            IPAAnsibleModule
+
+        def main():
+            ansible_module = IPAAnsibleModule(
+                argument_spec=dict(
+                      name=dict(type="str", aliases=["cn"], default=None),
+                      state=dict(type="str", default="present",
+                                 choices=["present", "absent"]),
+                ),
+            )
+
+            # Get parameters
+            name = ansible_module.params_get("name")
+            state = ansible_module.params_get("state")
+
+            # Connect to IPA API
+            with ansible_module.ipa_connect():
+
+                # Execute command
+                if state == "present":
+                    ansible_module.ipa_command(["command_add", name, {}])
+                else:
+                    ansible_module.ipa_command(["command_del", name, {}])
+
+            # Done
+
+            ansible_module.exit_json(changed=True)
+
+        if __name__ == "__main__":
+            main()
+
+        """
+
+        def __init__(self, *args, **kwargs):
+            # Extend argument_spec with ipamodule_base_spec
+            if "argument_spec" in kwargs:
+                _spec = kwargs["argument_spec"]
+                _spec.update(ipamodule_base_spec)
+                kwargs["argument_spec"] = _spec
+
+            # pylint: disable=super-with-arguments
+            super(IPAAnsibleModule, self).__init__(*args, **kwargs)
+
+            # ipaadmin vars
+            self.ipaadmin_principal = self.params_get("ipaadmin_principal")
+            self.ipaadmin_password = self.params_get("ipaadmin_password")
+
+            # Attributes to store kerberos credentials (if needed)
+            self.ccache_dir = None
+            self.ccache_name = None
+
+        @contextmanager
+        def ipa_connect(self, context=None):
+            ccache_dir = None
+            ccache_name = None
+            try:
+                if not valid_creds(self, self.ipaadmin_principal):
+                    ccache_dir, ccache_name = temp_kinit(
+                        self.ipaadmin_principal, self.ipaadmin_password)
+                api_connect(context)
+            except Exception as e:
+                self.fail_json(msg=str(e))
+            else:
+                try:
+                    yield ccache_name
+                except Exception as e:
+                    self.fail_json(msg=str(e))
+                finally:
+                    temp_kdestroy(ccache_dir, ccache_name)
+
+        def params_get(self, name):
+            return module_params_get(self, name)
+
+        def ipa_command(self, command, name, args):
+            return api_command(self, command, name, args)
+
+        def ipa_command_no_name(self, command, args):
+            return api_command_no_name(self, command, args)
+
+        def ipa_get_domain(self):  # pylint: disable=R0201
+            return api_get_domain()
+
+        def ipa_get_realm(self):  # pylint: disable=R0201
+            return api_get_realm()
+
+        def ipa_command_exists(self, command):  # pylint: disable=R0201
+            return api_check_command(command)
+
+        # pylint: disable=R0201
+        def ipa_command_param_exists(self, command, name):
+            return api_check_param(command, name)
+
+        # pylint: disable=R0201
+        def ipa_check_version(self, oper, requested_version):
+            return api_check_ipa_version(oper, requested_version)