Source code for insights.parsers.dse_ldif

"""
DseLDIF - file ``/etc/dirsrv/*/dse.ldif``
=========================================
"""

from collections import defaultdict

from insights import Parser, parser
from insights.core.exceptions import SkipComponent
from insights.core.filters import add_filter
from insights.specs import Specs

add_filter(Specs.dse_ldif, 'dn:')


[docs] @parser(Specs.dse_ldif) class DseLDIF(Parser, list): """ Parse the attributes out of the filtered lines of the ``/etc/dirsrv/*/dse.ldif`` file into a list of records. Each record will be stored as a defaultdict(list), take attribute name as the dict key, and wrap the attribute's values into a list as the dict value. The ``dse.ldif`` files are in the LDIF format (see ``man 5 ldif``). Due to the file content are filtered, there are some differences between the formal LDIF format and this parser. LDIF contains multi-row records where each record is identified by a ``dn:`` line ("dn" as in "distinguished name") and the record's other lines are attributes. Attributes may also have base64-encoded values, multiline values, and file-stored values. LDIF supports multiline values via continuing lines, one can break and continue a line or fold a line by indenting the continued portion of the line by one space. Since the content to be handled here is filtered content, the LDIF's continuing lines will be broken and no more trustable. When parsing, this parser will drop the lines startswith one space. This is acceptable for the current usage of the filter content. We can see to workaround this if continuing line requirement comes in the future. In the parsing process, line for ``dn:`` attribute will be recognized as the start of a record, the following lines will be included in this same record. Therefor, "dn:" is a default filter for the content collection. And a suggested way for filter adding is using the attribute key with ":" to minimize the collected data, eg. ``add_filter(Specs.dse_ldif, 'nsSSL3:')``. Sample input data:: dn: cn=config nsslapd-return-default-opattr: namingContexts nsslapd-return-default-opattr: supportedControl nsslapd-securePort: 636 nsslapd-security: on dn: cn=encryption,cn=config sslVersionMin: SSLv3 sslVersionMax: TLS1.1 nsSSL3: on Examples: >>> type(dse_ldif) <class 'insights.parsers.dse_ldif.DseLDIF'> >>> len(dse_ldif) 2 >>> dse_ldif[0]["nsslapd-return-default-opattr"] ['namingContexts', 'supportedControl'] >>> dse_ldif[0]["nsslapd-security"] ['on'] >>> "sslVersionMin" in dse_ldif[1] True >>> dse_ldif[1]["nsSSL3"][0] 'on' """
[docs] def parse_content(self, content): if not content: raise SkipComponent('Empty file content') records = [] attr_kval = defaultdict(list) for line in content: # empty lines or lines beginning with # are ignored if not line or line.startswith("#"): continue # the continuing lines are ignored if line.startswith(" "): continue # lines not in attributes format are ignored if ":" not in line: continue attr_name, attr_value = [_.strip() for _ in line.split(':', 1)] if attr_name == 'dn': # line starts with 'dn:', taken as the start of a new record attr_kval = defaultdict(list) records.append(attr_kval) attr_kval[attr_name].append(attr_value) else: if attr_value.startswith(":"): # base64-encrypted values not supported continue if attr_value.startswith("<"): # file-backed values not supported continue attr_kval[attr_name].append(attr_value) for record in records: self.append(dict(record)) if not self: raise SkipComponent("No valid content")