From 09307cc58a69bf70e7cba064948696af4fa4f530 Mon Sep 17 00:00:00 2001
From: anima
Date: Fri, 31 Jan 2025 22:29:17 +0100
Subject: [PATCH] inital version
---
Dockerfile | 64 +++++++++++++++++++++
conf_icigaweb2.py | 140 ++++++++++++++++++++++++++++++++++++++++++++++
init.sh | 38 +++++++++++++
3 files changed, 242 insertions(+)
create mode 100644 Dockerfile
create mode 100644 conf_icigaweb2.py
create mode 100644 init.sh
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0da35fb
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,64 @@
+FROM debian:bookworm-slim
+LABEL maintainer="docker@ao-it.net"
+
+## prepare requirements
+RUN ["bash", "-exo", "pipefail", "-c", "\
+ export DEBIAN_FRONTEND=noninteractive ; \
+ apt update ; \
+ apt install -y wget gnupg python3 python3-mysqldb; \
+ wget -O - https://packages.icinga.com/icinga.key | \
+ gpg --dearmor -o /usr/share/keyrings/icinga-archive-keyring.gpg ; \
+ source /etc/os-release ; \
+ echo \"deb [signed-by=/usr/share/keyrings/icinga-archive-keyring.gpg] https://packages.icinga.com/debian icinga-${VERSION_CODENAME} main\" > /etc/apt/sources.list.d/${VERSION_CODENAME}-icinga.list ; \
+ echo \"deb-src [signed-by=/usr/share/keyrings/icinga-archive-keyring.gpg] https://packages.icinga.com/debian icinga-${VERSION_CODENAME} main\" >> /etc/apt/sources.list.d/${VERSION_CODENAME}-icinga.list ; \
+ apt clean all ; \
+ rm -vrf /var/lib/apt/lists/* "]
+
+## install webserver
+RUN ["bash", "-exo", "pipefail", "-c", "\
+ export DEBIAN_FRONTEND=noninteractive ; \
+ apt update ; \
+ apt install -y --no-install-{recommends,suggests} apache2 ca-certificates libapache2-mod-php8.2 libldap-common locales-all php-{imagick,redis} php8.2-{bcmath,bz2,common,curl,dba,enchant,gd,gmp,imap,interbase,intl,ldap,mbstring,mysql,odbc,opcache,pgsql,pspell,readline,snmp,soap,sqlite3,sybase,tidy,xml,xmlrpc,xsl,zip} ; \
+ apt clean all ; \
+ rm -vrf /var/lib/apt/lists/* "]
+
+
+## install icingaweb2
+RUN ["bash", "-exo", "pipefail", "-c", "\
+ export DEBIAN_FRONTEND=noninteractive ; \
+ apt update ; \
+ apt install -y icingaweb2 icingadb-web icingacli ; \
+ ln -vs /usr/share/icingaweb2/bin/icingacli /usr/local/bin/ ; \
+ rm -f /etc/apache2/conf-enabled/icingaweb2.conf ; \
+ icingacli setup config webserver apache --path=/ --file=/etc/apache2/conf-enabled/icingaweb2.conf ; \
+ echo 'SetEnvIf X-REMOTE-USER \"(.*)\" REMOTE_USER=$0' > /etc/apache2/conf-enabled/allow-remote-user.conf ; \
+ apt clean all ; \
+ rm -vrf /var/lib/apt/lists/* "]
+
+## create persistend data store
+RUN ["bash", "-exo", "pipefail", "-c", "\
+ mkdir -p /data ; \
+ mkdir -p /data-init/etc/ ; \
+ mkdir -p /data-init/usr/ ; \
+ mv /etc/icingaweb2 /data-init/etc/ ; \
+ mv /usr/share/icingaweb2 /data-init/usr/ ; \
+ ln -vs /data/etc/icingaweb2 /etc/icingaweb2 ; \
+ ln -vs /data/usr/icingaweb2 /usr/share/icingaweb2 ; \
+"]
+
+## redirect log
+RUN ["bash", "-exo", "pipefail", "-c", "\
+ ln -vsf /dev/stdout /var/log/apache2/access.log ; \
+ ln -vsf /dev/stderr /var/log/apache2/error.log ; \
+ ln -vsf /dev/stdout /var/log/apache2/other_vhosts_access.log "]
+
+EXPOSE 8080
+
+COPY init.sh /root/init.sh
+COPY conf_icingaweb2.py /root/conf_icingaweb2.py
+
+VOLUME ["/data"]
+WORKDIR /data
+USER root
+ENTRYPOINT ["/bin/bash", "/root/init.sh"]
+CMD ["/usr/sbin/apache2", "-DFOREGROUND"]
\ No newline at end of file
diff --git a/conf_icigaweb2.py b/conf_icigaweb2.py
new file mode 100644
index 0000000..50323a7
--- /dev/null
+++ b/conf_icigaweb2.py
@@ -0,0 +1,140 @@
+#!/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):
+ """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()
+
+ 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)}
+ for env_var, value in env_vars.items():
+ tmp_list = env_var.split('.')
+ 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):
+ ## 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.' + os.environ['ICINGAWEB2_DB_RESOURCE_NAME']
+ self.host = os.environ[prefix + '.host'] # not check if exists
+ self.user = os.environ[prefix + '.username'] # not check if exists
+ self.passwd = os.environ[prefix + '.password'] # not check if exists
+ self.dbname = os.environ[prefix + '.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/'
+ ### config.ini : https://icinga.com/docs/icinga-web/latest/doc/03-Configuration/#configuration-general
+ IniFile(ICINGAWEB_CONFDIR + 'config.ini', 'ICINGAWEB2_CONF.')
+ ### resources.ini : https://icinga.com/docs/icinga-web/latest/doc/04-Resources/#resources
+ IniFile(ICINGAWEB_CONFDIR + 'resources.ini', 'ICINGAWEB2_RESOURCES.')
+ ### authentication.ini : https://icinga.com/docs/icinga-web/latest/doc/05-Authentication/#authentication
+ IniFile(ICINGAWEB_CONFDIR + 'authentication.ini', 'ICINGAWEB2_AUTH.')
+ ### groups.ini : https://icinga.com/docs/icinga-web/latest/doc/05-Authentication/#groups
+ IniFile(ICINGAWEB_CONFDIR + 'groups.ini', 'ICINGAWEB2_GROUPS.')
+ ### roles.ini : https://icinga.com/docs/icinga-web/latest/doc/06-Security/#roles
+ IniFile(ICINGAWEB_CONFDIR + 'roles.ini', 'ICINGAWEB2_ROLES.')
+
+ ## 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.')
+ ### redis.ini : https://icinga.com/docs/icinga-db-web/latest/doc/03-Configuration/#redis-configuration
+ IniFile(ICINGADB_WEB_CONFDIR + 'redis.ini', 'ICINGAWEB2_ICINGADB_REDIS.')
+ ### commandtransports.ini : https://icinga.com/docs/icinga-db-web/latest/doc/03-Configuration/#command-transport-configuration
+ IniFile(ICINGADB_WEB_CONFDIR + 'commandtransports.ini', 'ICINGAWEB2_ICINGADB_API.')
+
+ ## run db init
+ InitDB()
+
+if __name__ == '__main__':
+ main()
diff --git a/init.sh b/init.sh
new file mode 100644
index 0000000..7bf61c8
--- /dev/null
+++ b/init.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+ICINGAWEB2_FILE_APACHE_DEFAULT=/etc/apache2/sites-available/000-default.conf
+ICINGAWEB2_FILE_APACHE_PORTS=/etc/apache2/ports.conf
+ICINGAWEB2_PORT=8080
+
+## init icinga config files if need
+if [ -z "$(ls -A /data)" ]; then
+ ICINGAWEB2_CONF_ONCE=false
+ export INIT_DB=true
+
+ ## move init files
+ echo init icingaweb2 config
+ cp -ax /data-init/* /data
+ rm -rf /data-init
+
+ ## enable modules
+ icingacli module enable icingadb
+ mkdir -p /etc/icingaweb2/modules/icingadb/
+fi
+
+## apache setup
+if [ ! -z "$ICINGAWEB2_PORT" ]; then
+ echo set icingaweb2 apache ports
+ sed -i "s|^Listen .*|Listen $ICINGAWEB2_PORT|" $ICINGAWEB2_FILE_APACHE_PORTS
+ sed -i "s|VirtualHost \*:.*>|VirtualHost \*:$ICINGAWEB2_PORT>|g" $ICINGAWEB2_FILE_APACHE_DEFAULT
+fi
+
+## edit icingaweb2 config only on first setup or is enabled
+if [ ! $ICINGAWEB2_CONF_ONCE ] || [ "$ICINGAWEB2_CONF_ONCE" = false ]; then
+ /usr/bin/python3 /root/conf_icingaweb2.py
+fi
+
+## init apache
+. /etc/apache2/envvars
+
+# run CMD
+exec "$@"
\ No newline at end of file