#!/usr/bin/env python3 import configparser import os import MySQLdb import subprocess from time import sleep class IniFile: def __init__(self, file: str, prefix: str, delimiter: str = '__'): """class for edit a ini file Args: file (str): path to ini file to edit prefix (str): prefix of env vars for this file """ self.file = file self.prefix = prefix self.config = configparser.ConfigParser() self.delimiter = delimiter if os.path.exists(self.file): self.config.read(self.file) self.get_env_vars_with_prefix() self.save_changes() def get_env_vars_with_prefix(self): """read the environment and get all env start with prefix""" env_vars = {key: value for key, value in os.environ.items() if key.startswith(self.prefix + self.delimiter)} for env_var, value in env_vars.items(): tmp_list = env_var.split(self.delimiter) if len(tmp_list) == 3: _, section, key = tmp_list self.edit_ini(section, key, value) def edit_ini(self, section: str, key: str, value: str): """edit a single key / value of a section in ini file Args: section (str): section to edit or create key (str): key to edit or create in section value (str): value to set in key """ if section not in self.config: self.config[section] = {} self.config[section][key] = value def save_changes(self): """write the changes in file""" with open(self.file, 'w') as configfile: self.config.write(configfile) class InitDB: def __init__(self, delimiter: str = '__'): self.delimiter = delimiter ## check if all needes env vars a set required_env_vars = [ 'INIT_DB', 'ICINGAWEB2_DB_RESOURCE_NAME', 'ICINGAWEB2_DEFAULT_ADMIN_USER', 'ICINGAWEB2_DEFAULT_ADMIN_PASS' ] if all(key in os.environ.keys() for key in required_env_vars): prefix = 'ICINGAWEB2_RESOURCES' + self.delimiter + os.environ['ICINGAWEB2_DB_RESOURCE_NAME'] self.host = os.environ[prefix + self.delimiter + 'host'] # not check if exists self.user = os.environ[prefix + self.delimiter + 'username'] # not check if exists self.passwd = os.environ[prefix + self.delimiter + 'password'] # not check if exists self.dbname = os.environ[prefix + self.delimiter + 'dbname'] # not check if exists self.default_admin_user = os.environ['ICINGAWEB2_DEFAULT_ADMIN_USER'] self.default_admin_pass = os.environ['ICINGAWEB2_DEFAULT_ADMIN_PASS'] self.conn = self.db_conn() self.init_db() self.create_inital_admin() self.conn.close() def db_conn(self): max_trys = 7 trys = 0 while trys < max_trys: trys += 1 try: conn = MySQLdb.connect( host = self.host, db = self.dbname, user = self.user, passwd = self.passwd ) except MySQLdb._exceptions.OperationalError: print(f'can not connect the database {trys=} of {max_trys=}') sleep(5) else: print('connect to db successfully') return conn else: print('no connection to database, exit!') exit() def init_db(self): with open('/usr/share/icingaweb2/schema/mysql.schema.sql', "r", encoding="utf-8") as f: sql_script = f.read() with self.conn.cursor() as cursor: for statement in sql_script.split(";"): statement = statement.strip() if statement: # Leere Statements überspringen cursor.execute(statement) self.conn.commit() def create_inital_admin(self): php_command = f'php -r \'echo password_hash("{self.default_admin_pass}", PASSWORD_DEFAULT);\'' result = subprocess.run(php_command, shell=True, capture_output=True, text=True) hashed_pass = result.stdout.strip() with self.conn.cursor() as cursor: cursor.execute(""" INSERT INTO icingaweb_user (name, active, password_hash) VALUES (%s, '1', %s); """, (self.default_admin_user, hashed_pass)) self.conn.commit() def main(): ## icingaweb2 config ICINGAWEB_CONFDIR = '/etc/icingaweb2/' delimiter = '__' ### config.ini : https://icinga.com/docs/icinga-web/latest/doc/03-Configuration/#configuration-general IniFile(ICINGAWEB_CONFDIR + 'config.ini', 'ICINGAWEB2_CONF', delimiter) ### resources.ini : https://icinga.com/docs/icinga-web/latest/doc/04-Resources/#resources IniFile(ICINGAWEB_CONFDIR + 'resources.ini', 'ICINGAWEB2_RESOURCES', delimiter) ### authentication.ini : https://icinga.com/docs/icinga-web/latest/doc/05-Authentication/#authentication IniFile(ICINGAWEB_CONFDIR + 'authentication.ini', 'ICINGAWEB2_AUTH', delimiter) ### groups.ini : https://icinga.com/docs/icinga-web/latest/doc/05-Authentication/#groups IniFile(ICINGAWEB_CONFDIR + 'groups.ini', 'ICINGAWEB2_GROUPS', delimiter) ### roles.ini : https://icinga.com/docs/icinga-web/latest/doc/06-Security/#roles IniFile(ICINGAWEB_CONFDIR + 'roles.ini', 'ICINGAWEB2_ROLES', delimiter) ## icingaweb2 modul: icingadb web config ICINGADB_WEB_CONFDIR = ICINGAWEB_CONFDIR + 'modules/icingadb/' ### config.ini : https://icinga.com/docs/icinga-db-web/latest/doc/03-Configuration/#general-configuration IniFile(ICINGADB_WEB_CONFDIR + 'config.ini', 'ICINGAWEB2_ICINGADB_CONF', delimiter) ### redis.ini : https://icinga.com/docs/icinga-db-web/latest/doc/03-Configuration/#redis-configuration IniFile(ICINGADB_WEB_CONFDIR + 'redis.ini', 'ICINGAWEB2_ICINGADB_REDIS', delimiter) ### commandtransports.ini : https://icinga.com/docs/icinga-db-web/latest/doc/03-Configuration/#command-transport-configuration IniFile(ICINGADB_WEB_CONFDIR + 'commandtransports.ini', 'ICINGAWEB2_ICINGADB_CMD', delimiter) ## icingaweb2 modul: grafana ICINGAWEB_GRAFANA_CONFDIR = ICINGAWEB_CONFDIR + 'modules/grafana/' ### config.ini : https://github.com/NETWAYS/icingaweb2-module-grafana/blob/main/doc/03-module-configuration.md IniFile(ICINGAWEB_GRAFANA_CONFDIR + 'config.ini', 'ICINGAWEB2_GRAFANA_CONF', delimiter) ### graphs.ini : https://github.com/NETWAYS/icingaweb2-module-grafana/blob/main/doc/04-graph-configuration.md IniFile(ICINGAWEB_GRAFANA_CONFDIR + 'graphs.ini', 'ICINGAWEB2_GRAFANA_GRAPH', delimiter) ## run db init InitDB() if __name__ == '__main__': main()