diff --git a/docs/shared_parsers_catalog/auditctl.rst b/docs/shared_parsers_catalog/auditctl.rst
new file mode 100644
index 0000000000..83572e683c
--- /dev/null
+++ b/docs/shared_parsers_catalog/auditctl.rst
@@ -0,0 +1,3 @@
+.. automodule:: insights.parsers.auditctl
+   :members:
+   :show-inheritance:
diff --git a/insights/parsers/auditctl.py b/insights/parsers/auditctl.py
new file mode 100644
index 0000000000..d6188ec5c8
--- /dev/null
+++ b/insights/parsers/auditctl.py
@@ -0,0 +1,111 @@
+"""
+AuditCtl - command ``auditctl xxx``
+===================================
+
+This module contains the following parsers:
+
+AuditRules - command ``auditctl -l``
+------------------------------------
+AuditStatus - command ``auditctl -s``
+-------------------------------------
+
+"""
+
+from insights import parser, CommandParser
+from insights.parsers import ParseException, SkipException
+from insights.specs import Specs
+
+
+@parser(Specs.auditctl_rules)
+class AuditRules(CommandParser, list):
+    """
+    Class for parsing the `auditctl -l` command.
+    All lines are stored in a list.
+
+    Typical output of the command is::
+
+        -w /etc/selinux -p wa -k MAC-policy
+        -a always,exit -F arch=b32 -S chmod -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b64 -S chmod -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b32 -S chmod -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b64 -S chmod -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b32 -S chown -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b64 -S chown -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b32 -S chown -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+        -a always,exit -F arch=b64 -S chown -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+
+    Examples:
+        >>> type(audit_rules)
+        <class 'insights.parsers.auditctl.AuditRules'>
+        >>> len(audit_rules)
+        9
+        >>> '-w /etc/selinux -p wa -k MAC-policy' in audit_rules
+        True
+
+    Raises:
+        SkipException: When there are not rules.
+    """
+
+    def parse_content(self, content):
+        if len(content) == 1 and content[0].lower().strip() == 'no rules':
+            raise SkipException
+        for line in content:
+            if line.strip():
+                self.append(line.strip())
+        if not self:
+            raise SkipException('No rules found')
+
+
+@parser(Specs.auditctl_status)
+class AuditStatus(CommandParser, dict):
+    """
+    Module for parsing the output of the ``auditctl -s`` command.
+
+    Typical output on RHEL6 looks like::
+
+        AUDIT_STATUS: enabled=1 flag=1 pid=1483 rate_limit=0 backlog_limit=8192 lost=3 backlog=0
+
+    , while on RHEL7 and later, the output changes to::
+
+        enabled 1
+        failure 1
+        pid 947
+        rate_limit 0
+        backlog_limit 320
+        lost 0
+        backlog 0
+        loginuid_immutable 0 unlocked
+
+    Example:
+        >>> type(auds)
+        <class 'insights.parsers.auditctl.AuditStatus'>
+        >>> "enabled" in auds
+        True
+        >>> auds['enabled']
+        1
+    """
+    def parse_content(self, content):
+        if not content:
+            raise SkipException("Input content is empty.")
+        if len(content) > 1:
+            for line in content:
+                k, v = line.split(None, 1)
+                # Mind the 'loginuid_immutable' on RHEL7
+                if k.strip() == "loginuid_immutable":
+                    self[k.strip()] = v.strip()
+                else:
+                    try:
+                        self[k.strip()] = int(v.strip())
+                    except ValueError:
+                        raise ParseException('Unexpected type in line %s' % line)
+        if len(content) == 1:
+            line = list(content)[0].strip()
+            if line.startswith("AUDIT_STATUS:"):
+                for item in line.split(None)[1:]:
+                    try:
+                        k, v = item.split('=')
+                        self[k.strip()] = int(v.strip())
+                    except ValueError:
+                        raise ParseException('Unexpected type in line %s ' % line)
+        if not self:
+            raise SkipException('There is no content in the status output.')
diff --git a/insights/parsers/auditctl_status.py b/insights/parsers/auditctl_status.py
index 6a7aedecc8..2905b59967 100644
--- a/insights/parsers/auditctl_status.py
+++ b/insights/parsers/auditctl_status.py
@@ -6,11 +6,16 @@
 from .. import parser, CommandParser, LegacyItemAccess
 from ..parsers import ParseException
 from ..specs import Specs
+from insights.util import deprecated
 
 
 @parser(Specs.auditctl_status)
 class AuditctlStatus(LegacyItemAccess, CommandParser):
     """
+    .. warning::
+        This parser is deprecated, please use
+        :py:class:`insights.parsers.auditctl.AuditdStatus` instead.
+
     Module for parsing the output of the ``auditctl -s`` command.
 
     Typical output on RHEL6 looks like::
@@ -36,6 +41,14 @@ class AuditctlStatus(LegacyItemAccess, CommandParser):
         >>> auds['enabled']
         1
     """
+    def __init__(self, context):
+        deprecated(
+            AuditctlStatus,
+            "Please use the :class:`insights.parsers.auditctl.AuditdStatus` instead.",
+            "3.1.25"
+        )
+        super(AuditctlStatus, self).__init__(context)
+
     def parse_content(self, content):
         if not content:
             raise ParseException("Input content is empty.")
diff --git a/insights/specs/__init__.py b/insights/specs/__init__.py
index a54fa4f36d..3d6071d12b 100644
--- a/insights/specs/__init__.py
+++ b/insights/specs/__init__.py
@@ -7,6 +7,7 @@ class Specs(SpecSet):
     alternatives_display_python = RegistryPoint()
     amq_broker = RegistryPoint(multi_output=True)
     ansible_host = RegistryPoint()
+    auditctl_rules = RegistryPoint()
     auditctl_status = RegistryPoint()
     auditd_conf = RegistryPoint()
     audit_log = RegistryPoint(filterable=True)
diff --git a/insights/specs/default.py b/insights/specs/default.py
index 7d7bbacb40..b8da847685 100644
--- a/insights/specs/default.py
+++ b/insights/specs/default.py
@@ -67,6 +67,7 @@ class DefaultSpecs(Specs):
     alternatives_display_python = simple_command("/usr/sbin/alternatives --display python")
     amq_broker = glob_file("/var/opt/amq-broker/*/etc/broker.xml")
     dse_ldif = glob_file("/etc/dirsrv/*/dse.ldif")
+    auditctl_rules = simple_command("/sbin/auditctl -l")
     auditctl_status = simple_command("/sbin/auditctl -s")
     auditd_conf = simple_file("/etc/audit/auditd.conf")
     audit_log = simple_file("/var/log/audit/audit.log")
diff --git a/insights/specs/insights_archive.py b/insights/specs/insights_archive.py
index e62891e6e0..dfddbed737 100644
--- a/insights/specs/insights_archive.py
+++ b/insights/specs/insights_archive.py
@@ -14,6 +14,7 @@ class InsightsArchiveSpecs(Specs):
     all_installed_rpms = glob_file("insights_commands/rpm_-qa*")
     alternatives_display_python = simple_file("insights_commands/alternatives_--display_python")
     ansible_host = simple_file("ansible_host")
+    auditctl_rules = simple_file("insights_commands/auditctl_-l")
     auditctl_status = simple_file("insights_commands/auditctl_-s")
     aws_instance_id_doc = simple_file("insights_commands/python_-m_insights.tools.cat_--no-header_aws_instance_id_doc")
     aws_instance_id_pkcs7 = simple_file("insights_commands/python_-m_insights.tools.cat_--no-header_aws_instance_id_pkcs7")
diff --git a/insights/specs/sos_archive.py b/insights/specs/sos_archive.py
index 015f3ed060..0a4e375012 100644
--- a/insights/specs/sos_archive.py
+++ b/insights/specs/sos_archive.py
@@ -10,6 +10,7 @@
 
 class SosSpecs(Specs):
     alternatives_display_python = simple_file("sos_commands/alternatives/alternatives_--display_python")
+    auditctl_rules = simple_file("sos_commands/auditd/auditctl_-l")
     auditctl_status = simple_file("sos_commands/auditd/auditctl_-s")
     auditd_conf = simple_file("/etc/audit/auditd.conf")
     autofs_conf = simple_file("/etc/autofs.conf")
diff --git a/insights/tests/parsers/test_auditctl.py b/insights/tests/parsers/test_auditctl.py
new file mode 100644
index 0000000000..a83985f9db
--- /dev/null
+++ b/insights/tests/parsers/test_auditctl.py
@@ -0,0 +1,125 @@
+import pytest
+import doctest
+
+from insights.tests import context_wrap
+from insights.parsers import auditctl
+from insights.parsers.auditctl import AuditStatus, AuditRules
+from insights.parsers import ParseException, SkipException
+
+
+NORMAL_AUDS_RHEL6 = """
+AUDIT_STATUS: enabled=1 flag=1 pid=1483 rate_limit=0 backlog_limit=8192 lost=3 backlog=0
+""".strip()
+
+BAD_AUDS_RHEL6 = """
+AUDIT_STATUS: enabled=1 flag=1 pid=1483 rate_limit=0 backlog_limit=8192 lost=3 backlog=0 test=test
+""".strip()
+
+NORMAL_AUDS_RHEL7 = """
+enabled 1
+failure 1
+pid 947
+rate_limit 0
+backlog_limit 320
+lost 0
+backlog 0
+loginuid_immutable 1 locked
+""".strip()
+
+BAD_AUDS_RHEL7 = """
+enabled 1
+failure 1
+pid 947
+rate_limit 0
+backlog_limit 320
+lost 0
+backlog 0
+test test
+loginuid_immutable 1 locked
+""".strip()
+
+BLANK_INPUT_SAMPLE = """
+""".strip()
+
+BAD_INPUT_SAMPLE = """
+Unknown: type=0, len=0
+""".strip()
+
+BAD_INPUT_MIX = """
+Unknown: type=0, len=0
+enabled 1
+""".strip()
+
+AUDIT_RULES_OUTPUT1 = """
+No rules
+""".strip()
+
+AUDIT_RULES_OUTPUT2 = """
+-w /etc/selinux -p wa -k MAC-policy
+-a always,exit -F arch=b32 -S chmod -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b64 -S chmod -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b32 -S chmod -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b64 -S chmod -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+
+-a always,exit -F arch=b32 -S chown -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b64 -S chown -F exit=-EACCES -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b32 -S chown -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+-a always,exit -F arch=b64 -S chown -F exit=-EPERM -F auid>=1000 -F auid!=-1 -F key=access
+""".strip()
+
+AUDIT_RULES_OUTPUT3 = """
+
+"""
+
+
+def test_normal_auds_rhel6():
+    auds = AuditStatus(context_wrap(NORMAL_AUDS_RHEL6))
+    assert "enabled" in auds
+    assert "loginuid_immutable" not in auds
+    assert auds['pid'] == 1483
+
+
+def test_normal_auds_rhel7():
+    auds = AuditStatus(context_wrap(NORMAL_AUDS_RHEL7))
+    assert "loginuid_immutable" in auds
+    assert auds['loginuid_immutable'] == "1 locked"
+    assert auds['failure'] == 1
+    assert auds.get('nonexists') is None
+
+
+def test_auds_blank_input():
+    ctx = context_wrap(BLANK_INPUT_SAMPLE)
+    with pytest.raises(SkipException) as sc:
+        AuditStatus(ctx)
+    assert "Input content is empty." in str(sc)
+    with pytest.raises(SkipException):
+        AuditStatus(context_wrap(BAD_INPUT_SAMPLE))
+
+
+def test_parse_exception():
+    with pytest.raises(ParseException):
+        AuditStatus(context_wrap(BAD_AUDS_RHEL7))
+    with pytest.raises(ParseException):
+        AuditStatus(context_wrap(BAD_AUDS_RHEL6))
+
+
+def test_audit_rules():
+    audit_rules = AuditRules(context_wrap(AUDIT_RULES_OUTPUT2))
+    assert len(audit_rules) == 9
+    assert '-w /etc/selinux -p wa -k MAC-policy' in audit_rules
+
+
+def test_audit_rules_exception():
+    with pytest.raises(SkipException):
+        AuditRules(context_wrap(AUDIT_RULES_OUTPUT1))
+    with pytest.raises(SkipException):
+        AuditRules(context_wrap(AUDIT_RULES_OUTPUT3))
+
+
+def test_doc_examples():
+    env = {
+        'audit_rules': AuditRules(context_wrap(AUDIT_RULES_OUTPUT2)),
+        'auds': AuditStatus(context_wrap(NORMAL_AUDS_RHEL7))
+    }
+    failed, total = doctest.testmod(auditctl, globs=env)
+    assert failed == 0