From 23e02090e0101b8f5d3272705b50f9289abd35b3 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Mon, 5 Dec 2022 14:43:48 -0800 Subject: [PATCH] add pgpass parser --- jc/lib.py | 1 + jc/parsers/pgpass.py | 110 ++++++++++++++++++++++++++++++ tests/fixtures/generic/pgpass.txt | 9 +++ 3 files changed, 120 insertions(+) create mode 100644 jc/parsers/pgpass.py create mode 100644 tests/fixtures/generic/pgpass.txt diff --git a/jc/lib.py b/jc/lib.py index 4ed763ce..e89660d3 100644 --- a/jc/lib.py +++ b/jc/lib.py @@ -87,6 +87,7 @@ parsers: List[str] = [ 'os-prober', 'passwd', 'pci-ids', + 'pgpass', 'pidstat', 'pidstat-s', 'ping', diff --git a/jc/parsers/pgpass.py b/jc/parsers/pgpass.py new file mode 100644 index 00000000..f4dcdbd0 --- /dev/null +++ b/jc/parsers/pgpass.py @@ -0,0 +1,110 @@ +"""jc - JSON Convert PostgreSQL password file parser + +<> + +Usage (cli): + + $ cat /var/lib/postgresql/.pgpass | jc --pgpass + +Usage (module): + + import jc + result = jc.parse('pgpass', postgres_password_file) + +Schema: + + [ + { + "pgpass": string, + "bar": boolean, + "baz": integer + } + ] + +Examples: + + $ cat /var/lib/postgresql/.pgpass | jc --pgpass -p + [] +""" +from typing import List, Dict +from jc.jc_types import JSONDictType +import jc.utils + + +class info(): + """Provides parser metadata (version, author, etc.)""" + version = '1.0' + description = 'PostgreSQL password file parser' + author = 'Kelly Brazil' + author_email = 'kellyjonbrazil@gmail.com' + compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'] + + +__version__ = info.version + + +def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]: + """ + Final processing to conform to the schema. + + Parameters: + + proc_data: (List of Dictionaries) raw structured data to process + + Returns: + + List of Dictionaries. Structured to conform to the schema. + """ + return proc_data + + +def parse( + data: str, + raw: bool = False, + quiet: bool = False +) -> List[JSONDictType]: + """ + Main text parsing function + + Parameters: + + data: (string) text data to parse + raw: (boolean) unprocessed output if True + quiet: (boolean) suppress warning messages if True + + Returns: + + List of Dictionaries. Raw or processed structured data. + """ + jc.utils.compatibility(__name__, info.compatible, quiet) + jc.utils.input_type_check(data) + + raw_output: List[Dict] = [] + + if jc.utils.has_data(data): + + for line in filter(None, data.splitlines()): + + # ignore comment lines + if line.strip().startswith('#'): + continue + + # convert escaped characters (\ and :) + line = line.replace(':', '\u2063') + line = line.replace('\\\\', '\\') + line = line.replace('\\\u2063', ':') + + # split on \u2063 + hostname, port, database, username, password = line.split('\u2063') + + raw_output.append( + { + 'hostname': hostname, + 'port': port, + 'database': database, + 'username': username, + 'password': password + } + ) + + return raw_output if raw else _process(raw_output) diff --git a/tests/fixtures/generic/pgpass.txt b/tests/fixtures/generic/pgpass.txt new file mode 100644 index 00000000..6007a73b --- /dev/null +++ b/tests/fixtures/generic/pgpass.txt @@ -0,0 +1,9 @@ +dbserver:443:db1:dbuser:pwd123 +dbserver2:8888:inventory:joeuser:abc123 +ax1234:1234:tables:dbadmin:password1 + +dbserver3:8888:inventory:joeuser:abc123 +# comment + +localhost:5555:table\\1:user\:w\:colon:password123 +hostname:port:database:username:password