From 50bc1674665a828e627e55da5b376cf56082a4cb Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Mon, 9 Sep 2024 14:11:15 +0200 Subject: [PATCH] Add password-file CLI argument - By using a simple line-in-file search we don't have to parse the Bareos configuration format and can use any key-value (key=value) file --- check_bareos.py | 40 +++++++++++++++++++++++++++++++++++++--- contrib/bareos-dir.conf | 4 ++++ test_check_bareos.py | 8 ++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 contrib/bareos-dir.conf diff --git a/check_bareos.py b/check_bareos.py index 0f5e354..3709961 100755 --- a/check_bareos.py +++ b/check_bareos.py @@ -58,6 +58,30 @@ } +def read_password_from_file(fp): + """ + Tries to read a password from the given file + This allows to extract the password from the Bareos configuration + or from any other file that contains 'Password = secretpassword' + """ + l = [] + pwd = None + # Extract the password from the given file + with open(fp, encoding='utf-8') as pwfile: + for line in pwfile: + line = line.strip() + if 'Password' in line: + l = line.split() + # Validate that we got a password + try: + pwd = l[2] + except IndexError: + pass + if not pwd: + raise ValueError('No password found in', fp) + + return pwd + def check_threshold(value, warning, critical): # checks a value against warning and critical thresholds if critical is not None: @@ -572,9 +596,15 @@ def environ_or_required(key): parser = argparse.ArgumentParser(description='Check Plugin for Bareos Backup Status') group = parser.add_argument_group() group.add_argument('-U', '--user', dest='user', action='store', required=True, help='user name for the database connections') - group.add_argument('-p', '--password', dest='password', action='store', - **environ_or_required('CHECK_BAREOS_DATABASE_PASSWORD'), - help='password for the database connections') + + password_group = group.add_mutually_exclusive_group() + + password_group.add_argument('-p', '--password', dest='password', action='store', + **environ_or_required('CHECK_BAREOS_DATABASE_PASSWORD'), + help='password for the database connections') + password_group.add_argument('--password-file', dest='password_file', action='store', + default='/etc/bareos/bareos-dir.conf', + help='path to a password file. Can be the bareos-dir.conf') group.add_argument('-H', '--Host', dest='host', action='store', help='database host', default="127.0.0.1") group.add_argument('-P', '--port', dest='port', action='store', help='database port', default=5432, type=int) @@ -718,6 +748,10 @@ def checkStatus(args): if __name__ == '__main__': # pragma: no cover try: ARGS = commandline(sys.argv[1:]) + + if ARGS.password_file and not ARGS.password: + ARGS.password = read_password_from_file(ARGS.password_file) + ARGS.func(ARGS) except SystemExit: # Re-throw the exception diff --git a/contrib/bareos-dir.conf b/contrib/bareos-dir.conf new file mode 100644 index 0000000..5630969 --- /dev/null +++ b/contrib/bareos-dir.conf @@ -0,0 +1,4 @@ +Director { + Name = bareos-dir + Password = secretpassword +} diff --git a/test_check_bareos.py b/test_check_bareos.py index b013837..f3040ca 100644 --- a/test_check_bareos.py +++ b/test_check_bareos.py @@ -9,6 +9,7 @@ from check_bareos import commandline +from check_bareos import read_password_from_file from check_bareos import createBackupKindString from check_bareos import createFactor from check_bareos import printNagiosOutput @@ -102,6 +103,13 @@ def test_printNagiosOutput(self, mock_print): actual = printNagiosOutput({'returnCode': 1, 'returnMessage': "bar", 'performanceData': 'foo'}) self.assertEqual(sysexit.exception.code, 1) + def test_read_password_from_file(self): + actual = read_password_from_file('contrib/bareos-dir.conf') + expected = 'secretpassword' + self.assertEqual(actual, expected) + + with self.assertRaises(FileNotFoundError) as sysexit: + read_password_from_file('contrib/nosuch') class SQLTesting(unittest.TestCase):