diff --git a/docs/shared_parsers_catalog/authselect.rst b/docs/shared_parsers_catalog/authselect.rst new file mode 100644 index 0000000000..e561fb817a --- /dev/null +++ b/docs/shared_parsers_catalog/authselect.rst @@ -0,0 +1,3 @@ +.. automodule:: insights.parsers.authselect + :members: + :show-inheritance: diff --git a/insights/parsers/authselect.py b/insights/parsers/authselect.py new file mode 100644 index 0000000000..36a609db12 --- /dev/null +++ b/insights/parsers/authselect.py @@ -0,0 +1,58 @@ +""" +AuthSelectCurrent - command ``authselect current`` +================================================== +""" +from insights import parser +from insights.core import CommandParser +from insights.parsers import SkipException +from insights.specs import Specs + + +@parser(Specs.authselect_current) +class AuthSelectCurrent(CommandParser): + """ + Class to parse the output of command "authselect current". + + Sample output of command ``authselect current``:: + + Profile ID: sssd + Enabled features: + - with-sudo + - with-mkhomedir + - with-smartcard + + Attributes: + profile_id (str): The enabled profile ID + enabled_features (list): List of enabled features + + Examples: + >>> asc.profile_id + 'sssd' + >>> len(asc.enabled_features) + 3 + >>> 'with-sudo' in asc.enabled_features + True + """ + def parse_content(self, content): + feature_flag = False + self.profile_id = None + self.enabled_features = [] + for line in content: + if 'No existing configuration detected.' in line: + raise SkipException + line_sp = line.split() + if line.startswith('Profile ID:'): + self.profile_id = line_sp[-1] + elif line.endswith('Enabled features:'): + # Enabled features: + # - ... + feature_flag = True + elif line.startswith('Enabled features:') and len(line_sp) > 2: + # Enabled features: None + feature_flag = True + if line_sp[-1] != 'None': + self.enabled_features.append(line_sp[-1]) + elif line.startswith('-') and feature_flag: + self.enabled_features.append(line_sp[-1]) + if self.profile_id is None: + raise SkipException diff --git a/insights/specs/__init__.py b/insights/specs/__init__.py index 3d6071d12b..3a6263869c 100644 --- a/insights/specs/__init__.py +++ b/insights/specs/__init__.py @@ -11,6 +11,7 @@ class Specs(SpecSet): auditctl_status = RegistryPoint() auditd_conf = RegistryPoint() audit_log = RegistryPoint(filterable=True) + authselect_current = RegistryPoint() autofs_conf = RegistryPoint() avc_hash_stats = RegistryPoint() avc_cache_threshold = RegistryPoint() diff --git a/insights/specs/default.py b/insights/specs/default.py index 99aeb5b1e6..89cc51cf2f 100644 --- a/insights/specs/default.py +++ b/insights/specs/default.py @@ -66,6 +66,7 @@ class DefaultSpecs(Specs): abrt_status_bare = simple_command("/usr/bin/abrt status --bare=True") alternatives_display_python = simple_command("/usr/sbin/alternatives --display python") amq_broker = glob_file("/var/opt/amq-broker/*/etc/broker.xml") + authselect_current = simple_command("/usr/bin/authselect current") dse_ldif = glob_file("/etc/dirsrv/*/dse.ldif") auditctl_rules = simple_command("/sbin/auditctl -l") auditctl_status = simple_command("/sbin/auditctl -s") diff --git a/insights/specs/insights_archive.py b/insights/specs/insights_archive.py index 029c48f2ca..785e14a58c 100644 --- a/insights/specs/insights_archive.py +++ b/insights/specs/insights_archive.py @@ -16,6 +16,7 @@ class InsightsArchiveSpecs(Specs): ansible_host = simple_file("ansible_host") auditctl_rules = simple_file("insights_commands/auditctl_-l") auditctl_status = simple_file("insights_commands/auditctl_-s") + authselect_current = simple_file("insights_commands/authselect_current") 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") awx_manage_check_license = simple_file("insights_commands/awx-manage_check_license") diff --git a/insights/tests/parsers/test_authselect.py b/insights/tests/parsers/test_authselect.py new file mode 100644 index 0000000000..29004b1a7a --- /dev/null +++ b/insights/tests/parsers/test_authselect.py @@ -0,0 +1,50 @@ +import pytest +import doctest +from insights.parsers.authselect import AuthSelectCurrent +from insights.parsers import SkipException, authselect +from insights.tests import context_wrap + +AUTHSELECT_CURRENT_1 = """ +Profile ID: sssd +Enabled features: +- with-sudo +- with-mkhomedir +- with-smartcard +""".strip() + +AUTHSELECT_CURRENT_2 = """ +Profile ID: custom/password-policy +Enabled features: None +""".strip() + +AUTHSELECT_CURRENT_EMPTY = "" + +AUTHSELECT_CURRENT_NG = """ +No existing configuration detected. +""".strip() + + +def test_authselect_current(): + asc = AuthSelectCurrent(context_wrap(AUTHSELECT_CURRENT_1)) + assert asc.profile_id == 'sssd' + assert asc.enabled_features == ['with-sudo', 'with-mkhomedir', 'with-smartcard'] + + asc = AuthSelectCurrent(context_wrap(AUTHSELECT_CURRENT_2)) + assert asc.profile_id == 'custom/password-policy' + assert asc.enabled_features == [] + + +def test_authselect_current_exp(): + with pytest.raises(SkipException): + AuthSelectCurrent(context_wrap(AUTHSELECT_CURRENT_EMPTY)) + + with pytest.raises(SkipException): + AuthSelectCurrent(context_wrap(AUTHSELECT_CURRENT_NG)) + + +def test_doc_examples(): + env = { + 'asc': AuthSelectCurrent(context_wrap(AUTHSELECT_CURRENT_1)) + } + failed, total = doctest.testmod(authselect, globs=env) + assert failed == 0