├── .gitattributes ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile.base ├── Dockerfile.master ├── Dockerfile.satellite ├── LICENSE ├── Makefile ├── README.md ├── build ├── check_mem ├── check_ssl_cert └── check_ssl_observatory ├── compose ├── config │ └── nginx.conf ├── database.yml ├── grafana.yml ├── graphite.yml ├── head.yml ├── icingaweb2.yml ├── import │ ├── dashboards │ │ ├── QA-Test.json │ │ ├── icinga2-default.json │ │ ├── icinga2-details.json │ │ └── itl-icinga_rev1.json │ ├── host_object_data.json │ ├── host_object_data_icinga2-satellite-2.matrix.lan.json │ ├── host_object_data_icinga2-satellite-2.matrix.lan_2.json │ └── provisioning │ │ ├── dashboards │ │ └── dashboards.yml │ │ ├── datasources │ │ └── datasource.yml │ │ └── notifiers │ │ └── notifier.yml ├── influxdb.yml ├── master.yml ├── nginx.yml ├── satellite.yml └── ssl │ ├── cert.pem │ ├── dh.pem │ └── key.pem ├── doc └── assets │ ├── master-satellite.jpg │ └── master-satellite.png ├── hooks ├── build ├── clean ├── compose-file ├── environment ├── exec ├── latest-version.sh ├── publish ├── run ├── shell ├── start └── stop ├── rootfs ├── etc │ ├── icinga2 │ │ ├── conf.d │ │ │ ├── api-users.conf │ │ │ ├── functions.conf │ │ │ ├── groups.conf │ │ │ ├── hosts.conf │ │ │ ├── satellite_hostgroup.conf │ │ │ └── services.conf.docker │ │ ├── constants.conf-SAVE │ │ ├── features-available │ │ │ └── livestatus.conf │ │ ├── icinga2.conf │ │ ├── master.d │ │ │ ├── checkcommands_linux_memory.conf │ │ │ ├── satellite_services.conf │ │ │ └── templates_services.conf │ │ ├── satellite.d │ │ │ ├── commands.conf │ │ │ └── services.conf │ │ └── zones.conf-docker │ └── s6 │ │ ├── .s6-svscan │ │ └── .keep │ │ ├── icinga2-cert-service │ │ └── run │ │ └── icinga2 │ │ └── run ├── init │ ├── api_user.sh │ ├── cert │ │ ├── certificate_handler.sh │ │ └── certificate_test.sh │ ├── common.sh │ ├── config_handler.sh │ ├── configure_icinga.sh │ ├── database │ │ ├── mysql.sh │ │ └── postgres.sh │ ├── demo │ │ ├── bp_cluster.conf │ │ ├── bp_groups.conf │ │ ├── bp_hosts.conf │ │ ├── bp_services.conf │ │ ├── cube_hosts.conf │ │ └── globe_hosts.conf │ ├── environment.sh │ ├── examples │ │ ├── cert-manager.sh │ │ ├── certificate_test.sh │ │ ├── create certificate.sh │ │ ├── iowatch.sh │ │ ├── master-key.sh │ │ ├── node-wizard.expect │ │ └── use_cert-service.sh │ ├── healthcheck.sh │ ├── icinga_types │ │ ├── agent.sh │ │ ├── master.sh │ │ ├── satellite.sh │ │ └── satellite.sh-SAVE │ ├── modules.d │ │ ├── graphite.sh │ │ ├── influxdb.sh │ │ └── msmtp.sh │ ├── node-wizard_old.expect │ ├── output.sh │ ├── run.sh │ ├── runtime │ │ ├── ca_validator.sh │ │ ├── inotify.sh │ │ ├── service_handler.sh │ │ ├── watch_satellites.sh │ │ ├── zone_debugger.sh │ │ └── zone_watcher.sh │ └── wait_for │ │ ├── cert_service.sh │ │ ├── dns.sh │ │ ├── icinga_master.sh │ │ ├── mysql.sh │ │ └── port.sh └── usr │ ├── bin │ └── vercomp │ └── lib │ └── monitoring-plugins │ ├── check_hostname │ ├── check_mysql_health │ ├── check_procs │ └── check_xping └── tests ├── integration_test.sh └── linter.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | *OBSOLETE 4 | docker-compose.yml 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: ruby 3 | services: 4 | - docker 5 | env: 6 | global: 7 | - ICINGA2_VERSION=$(./hooks/latest-version.sh) 8 | - BUILD_DATE=$(date +"%Y-%m-%d") 9 | - BUILD_IMAGE=bodsch/docker-icinga2:${ICINGA2_VERSION}-base 10 | - secure: cnuQOWTh8TImJWlxcSJRzOfxkZYndXU60iuXVGI54EEyLStxwRRETKBWS2gADwOhsdUY105YyWEwSA0uTTERolBX6mXtDBJSxzVfW+sOE36pCISv/L/EZhK6pDxfsl9Q72GmdcSIT5DVXblTjIBvN1Jh+Jdymao/QoFC3g7JAwossXCi8WXdPL9uZeNWunFM6i28bgtv/6hMJ4kp2ga65ZvvzxbrrY/9yVZjjLAYWOidAZ77LnzvV3TP5KE7LwpfipkVyCG+w4JKnop5/wFO8c/BcYwEF4fdEdbWh+40nJAsfUJXMAPVjTvdQgwpysneMU5oHGMos09wjm4EUce3Yifm6iCMtKcEZ0svCdeY8/r2t5Voyu1e+1Hk7/X1XhwUg3t5H4MlkUN5I0TMkbFMGklfJ5e3VX+OQjHCTrLUqtjHkGBE2/HlgONgB0dNS2Atmtntvvhm5N6FJbM2Sjx47EzSGwlVee2yXXQ7MGHqW129Ykk6ETBUFSOV7x2HyGPd/tWf4ZCm7D1lrCueEjmFyDv8t+VjsAQrDEq/QCnJ7C2sWjQw06q+bYg5kYMSE7eSqF8uPoHqEOW7M5bOnN8eLcbhMVh7jRkbizxabrQ7sh+mvh1zOTmSGDZWROaH2GfoBlPsConMRYfbkEfO1ljtQXVUuBGHHEpB+cC4PEor6Qg= 11 | jobs: 12 | include: 13 | - stage: build and publish base image 14 | script: 15 | - make base-build 16 | - docker login --username "${DOCKER_USERNAME}" --password "${DOCKER_PASSWORD}" 17 | - make publish-base 18 | - docker logout 19 | - stage: push latest docker image 20 | if: branch = master 21 | script: 22 | - make 23 | - docker login --username "${DOCKER_USERNAME}" --password "${DOCKER_PASSWORD}" 24 | - docker tag ${USER}/icinga2:latest-master ${DOCKER_USERNAME}/docker-icinga2:latest-master 25 | - docker tag ${USER}/icinga2:latest-satellite ${DOCKER_USERNAME}/docker-icinga2:latest-satellite 26 | - docker push ${DOCKER_USERNAME}/docker-icinga2:latest-master 27 | - docker push ${DOCKER_USERNAME}/docker-icinga2:latest-satellite 28 | - docker logout 29 | - stage: push version docker image 30 | if: branch = master 31 | script: 32 | - make 33 | - docker login --username "${DOCKER_USERNAME}" --password "${DOCKER_PASSWORD}" 34 | - docker tag ${USER}/icinga2:latest-master ${DOCKER_USERNAME}/docker-icinga2:${ICINGA2_VERSION}-master 35 | - docker tag ${USER}/icinga2:latest-satellite ${DOCKER_USERNAME}/docker-icinga2:${ICINGA2_VERSION}-satellite 36 | - docker push ${DOCKER_USERNAME}/docker-icinga2:${ICINGA2_VERSION}-master 37 | - docker push ${DOCKER_USERNAME}/docker-icinga2:${ICINGA2_VERSION}-satellite 38 | - docker logout 39 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | If you want to contribute to a project and make it better, your help is very welcome. 4 | Contributing is also a great way to learn more about social coding on Github, new technologies and 5 | and their ecosystems and how to make constructive, helpful bug reports, feature requests and the 6 | noblest of all contributions: a good, clean pull request. 7 | 8 | ### How to make a clean pull request 9 | 10 | Look for a project's contribution instructions. If there are any, follow them. 11 | 12 | - Create a personal fork of the project on Github. 13 | - Clone the fork on your local machine. Your remote repo on Github is called `origin`. 14 | - Add the original repository as a remote called `upstream`. 15 | - If you created your fork a while ago be sure to pull upstream changes into your local repository. 16 | - Create a new branch to work on! Branch from `develop` if it exists, else from `master`. 17 | - Implement/fix your feature, comment your code. 18 | - Follow the code style of the project, including indentation. 19 | - If the project has tests run them! 20 | - Write or adapt tests as needed. 21 | - Add or change the documentation as needed. 22 | - Squash your commits into a single commit with git's [interactive rebase](https://help.github.com/articles/interactive-rebase). Create a new branch if necessary. 23 | - Push your branch to your fork on Github, the remote `origin`. 24 | - From your fork open a pull request in the correct branch. Target the project's `develop` branch if there is one, else go for `master`! 25 | - If the maintainer requests further changes just push them to your branch. The PR will be updated automatically. 26 | - Once the pull request is approved and merged you can pull the changes from `upstream` to your local repo and delete 27 | your extra branch(es). 28 | 29 | And last but not least: Always write your commit messages in the present tense. 30 | Your commit message should describe what the commit, when applied, does to the 31 | code – not what you did to the code. 32 | -------------------------------------------------------------------------------- /Dockerfile.base: -------------------------------------------------------------------------------- 1 | ARG BUILD_BASE 2 | # hadolint ignore=DL3006 3 | FROM $BUILD_BASE 4 | # FROM ubuntu:19.04 5 | # FROM debian:9-slim 6 | 7 | ARG BUILD_DATE 8 | ARG BUILD_VERSION 9 | ARG ICINGA2_VERSION 10 | ARG CERT_SERVICE_TYPE 11 | ARG CERT_SERVICE_VERSION 12 | 13 | ENV \ 14 | TERM=xterm \ 15 | DEBIAN_FRONTEND=noninteractive \ 16 | TZ='Europe/Berlin' 17 | 18 | # --------------------------------------------------------------------------------------- 19 | 20 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 21 | 22 | # hadolint ignore=DL3008,DL3014,DL3015,DL3027,DL4005,SC1091,SC2155 23 | RUN \ 24 | chsh -s /bin/bash && \ 25 | ln -sf /bin/bash /bin/sh && \ 26 | ln -sf "/usr/share/zoneinfo/${TZ}" /etc/localtime && \ 27 | ln -s /etc/default /etc/sysconfig && \ 28 | apt-get remove \ 29 | --allow-remove-essential \ 30 | --assume-yes \ 31 | --purge \ 32 | e2fsprogs libext2fs2 && \ 33 | apt-get update && \ 34 | apt-get install \ 35 | --assume-yes \ 36 | --no-install-recommends \ 37 | apt-utils && \ 38 | apt-get dist-upgrade \ 39 | --assume-yes && \ 40 | apt-get install \ 41 | --assume-yes \ 42 | ca-certificates \ 43 | curl \ 44 | gnupg > /dev/null && \ 45 | curl \ 46 | --silent \ 47 | https://packages.icinga.com/icinga.key | apt-key add - && \ 48 | . /etc/os-release && \ 49 | if [ "${ID}" = "ubuntu" ]; then \ 50 | if [ -n "${UBUNTU_CODENAME+x}" ]; then \ 51 | DIST="${UBUNTU_CODENAME}"; \ 52 | else \ 53 | DIST="$(lsb_release -c | awk '{print $2}')"; \ 54 | fi \ 55 | elif [ "${ID}" = "debian" ]; then \ 56 | DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release) ;\ 57 | fi && \ 58 | echo " => ${ID} - ${DIST}" && \ 59 | echo "deb http://packages.icinga.com/${ID} icinga-${DIST} main" > "/etc/apt/sources.list.d/${DIST}-icinga.list" && \ 60 | apt-get update && \ 61 | apt-get install \ 62 | --assume-yes \ 63 | --no-install-recommends \ 64 | icinga2-bin \ 65 | icinga2-ido-mysql \ 66 | monitoring-plugins \ 67 | dnsutils \ 68 | file \ 69 | fping \ 70 | inotify-tools \ 71 | jq \ 72 | netcat-openbsd \ 73 | psmisc \ 74 | pwgen \ 75 | python3.5-minimal \ 76 | libtext-english-perl \ 77 | tzdata \ 78 | unzip \ 79 | xz-utils && \ 80 | mkdir -p /etc/icinga2/objects.d && \ 81 | mkdir -p /run/icinga2/cmd && \ 82 | mkdir -p /etc/icinga2/zones.d/global-templates && \ 83 | mkdir -p /etc/icinga2/zones.d/director-global && \ 84 | cp /etc/icinga2/zones.conf /etc/icinga2/zones.conf-distributed && \ 85 | apt-get remove \ 86 | --assume-yes \ 87 | --purge \ 88 | gnupg && \ 89 | apt-get clean && \ 90 | apt autoremove \ 91 | --assume-yes && \ 92 | rm -rf \ 93 | /tmp/* \ 94 | /var/cache/debconf/* \ 95 | /usr/share/doc/* \ 96 | /root/.gem \ 97 | /root/.cache \ 98 | /root/.bundle 2> /dev/null && \ 99 | find /var/log -type f -print0 | while IFS= read -r -d '' i; do echo "" > "${i}"; done && \ 100 | echo "" && \ 101 | command -v icinga2 && \ 102 | icinga2 --version && \ 103 | icinga2 daemon --validate && \ 104 | icinga2 feature list && \ 105 | echo "" && \ 106 | export ICINGA2_VERSION=$(icinga2 --version | head -n1 | awk -F 'version: ' '{printf $2}' | awk -F '-' '{print $1}' | sed 's|r||') && \ 107 | echo "export BUILD_DATE=${BUILD_DATE}" > /etc/profile.d/icinga2.sh && \ 108 | echo "export BUILD_VERSION=${BUILD_VERSION}" >> /etc/profile.d/icinga2.sh && \ 109 | echo "export ICINGA2_VERSION=${ICINGA2_VERSION}" >> /etc/profile.d/icinga2.sh 110 | 111 | COPY rootfs/ / 112 | COPY build/check_mem /usr/lib/nagios/plugins/check_mem 113 | COPY build/check_ssl_cert /usr/lib/nagios/plugins/check_ssl_cert 114 | 115 | WORKDIR /etc/icinga2 116 | VOLUME ["/etc/icinga2", "/var/lib/icinga2", "/var/spool/icinga2", "/var/cache/icinga2"] 117 | 118 | CMD ["/init/run.sh"] 119 | 120 | HEALTHCHECK \ 121 | --interval=30s \ 122 | --timeout=2s \ 123 | --retries=10 \ 124 | --start-period=15s \ 125 | CMD /init/healthcheck.sh 126 | 127 | # --------------------------------------------------------------------------------------- 128 | -------------------------------------------------------------------------------- /Dockerfile.master: -------------------------------------------------------------------------------- 1 | ARG BUILD_IMAGE 2 | # hadolint ignore=DL3006 3 | FROM $BUILD_IMAGE 4 | 5 | ARG BUILD_DATE 6 | ARG BUILD_VERSION 7 | ARG ICINGA2_VERSION 8 | ARG CERT_SERVICE_TYPE 9 | ARG CERT_SERVICE_VERSION 10 | 11 | ENV \ 12 | TERM=xterm \ 13 | DEBIAN_FRONTEND=noninteractive \ 14 | TZ='Europe/Berlin' 15 | 16 | EXPOSE 5665 8080 17 | 18 | # --------------------------------------------------------------------------------------- 19 | 20 | COPY build/ruby-icinga-cert-service /tmp/ruby-icinga-cert-service 21 | 22 | WORKDIR /tmp 23 | 24 | # hadolint ignore=DL3003,DL3008,DL3014,DL3027,DL3028 25 | RUN \ 26 | export ICINGA2_TYPE=Master && \ 27 | apt-get install \ 28 | --assume-yes \ 29 | --no-install-recommends \ 30 | libffi-dev \ 31 | g++ \ 32 | make \ 33 | git \ 34 | libssl-dev \ 35 | ruby-dev \ 36 | bind9utils \ 37 | bsd-mailx \ 38 | mariadb-client \ 39 | nagios-nrpe-server \ 40 | openssl \ 41 | ruby \ 42 | bundler \ 43 | ssmtp && \ 44 | echo 'gem: --no-document' >> /etc/gemrc && \ 45 | gem install --quiet --no-rdoc --no-ri \ 46 | io-console bundler && \ 47 | bash /tmp/ruby-icinga-cert-service/bin/installer.sh && \ 48 | apt-get remove \ 49 | --assume-yes \ 50 | --purge \ 51 | apt-utils \ 52 | libffi-dev \ 53 | gcc \ 54 | make \ 55 | git \ 56 | gnupg \ 57 | libssl-dev \ 58 | ruby-dev \ 59 | python3-pip && \ 60 | rm -f /etc/apt/sources.list.d/* && \ 61 | apt-get clean && \ 62 | apt autoremove \ 63 | --assume-yes && \ 64 | rm -rf \ 65 | /tmp/* \ 66 | /var/cache/debconf/* \ 67 | /usr/share/doc/* \ 68 | /root/.gem \ 69 | /root/.cache \ 70 | /root/.bundle 2> /dev/null && \ 71 | echo "export ICINGA2_TYPE=${ICINGA2_TYPE}" >> /etc/profile.d/icinga2.sh 72 | 73 | WORKDIR /etc/icinga2 74 | 75 | # --------------------------------------------------------------------------------------- 76 | 77 | LABEL \ 78 | version="${BUILD_VERSION}" \ 79 | maintainer="Bodo Schulz " \ 80 | org.label-schema.build-date=${BUILD_DATE} \ 81 | org.label-schema.name="Icinga2 Docker Image" \ 82 | org.label-schema.vcs-ref=${VCS_REF} \ 83 | org.label-schema.description="Inofficial Icinga2 Docker Image" \ 84 | org.label-schema.url="https://www.icinga.org/" \ 85 | org.label-schema.vcs-url="https://github.com/bodsch/docker-icinga2" \ 86 | org.label-schema.vendor="Bodo Schulz" \ 87 | org.label-schema.version=${ICINGA2_VERSION} \ 88 | org.label-schema.schema-version="1.0" \ 89 | com.microscaling.docker.dockerfile="/Dockerfile" \ 90 | com.microscaling.license="GNU General Public License v3.0" 91 | 92 | # --------------------------------------------------------------------------------------- 93 | -------------------------------------------------------------------------------- /Dockerfile.satellite: -------------------------------------------------------------------------------- 1 | ARG BUILD_IMAGE 2 | # hadolint ignore=DL3006 3 | FROM $BUILD_IMAGE 4 | 5 | ARG BUILD_DATE 6 | ARG BUILD_VERSION 7 | ARG ICINGA2_VERSION 8 | 9 | ENV \ 10 | TERM=xterm \ 11 | DEBIAN_FRONTEND=noninteractive \ 12 | TZ='Europe/Berlin' 13 | 14 | EXPOSE 5665 15 | 16 | # --------------------------------------------------------------------------------------- 17 | 18 | # hadolint ignore=DL3027 19 | RUN \ 20 | export ICINGA2_TYPE=Satellite && \ 21 | export APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 && \ 22 | apt-get remove \ 23 | --assume-yes \ 24 | --purge \ 25 | apt-utils \ 26 | libffi-dev \ 27 | gcc \ 28 | make \ 29 | git \ 30 | libssl-dev \ 31 | ruby-dev \ 32 | python3-pip && \ 33 | rm -f /etc/apt/sources.list.d/* && \ 34 | apt-get clean && \ 35 | apt autoremove \ 36 | --assume-yes && \ 37 | rm -rf \ 38 | /tmp/* \ 39 | /var/cache/debconf/* \ 40 | /usr/share/doc/* \ 41 | /root/.gem \ 42 | /root/.cache \ 43 | /root/.bundle 2> /dev/null && \ 44 | echo "export ICINGA2_TYPE=${ICINGA2_TYPE}" >> /etc/profile.d/icinga2.sh 45 | 46 | # --------------------------------------------------------------------------------------- 47 | 48 | LABEL \ 49 | version="${BUILD_VERSION}" \ 50 | maintainer="Bodo Schulz " \ 51 | org.label-schema.build-date=${BUILD_DATE} \ 52 | org.label-schema.name="Icinga2 Docker Image" \ 53 | org.label-schema.vcs-ref=${VCS_REF} \ 54 | org.label-schema.description="Inofficial Icinga2 Docker Image" \ 55 | org.label-schema.url="https://www.icinga.org/" \ 56 | org.label-schema.vcs-url="https://github.com/bodsch/docker-icinga2" \ 57 | org.label-schema.vendor="Bodo Schulz" \ 58 | org.label-schema.version=${ICINGA2_VERSION} \ 59 | org.label-schema.schema-version="1.0" \ 60 | com.microscaling.docker.dockerfile="/Dockerfile" \ 61 | com.microscaling.license="GNU General Public License v3.0" 62 | 63 | # --------------------------------------------------------------------------------------- 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export GIT_SHA1 := $(shell git rev-parse --short HEAD) 2 | export DOCKER_IMAGE_NAME := icinga2 3 | export DOCKER_NAME_SPACE := ${USER} 4 | export DOCKER_VERSION ?= latest 5 | export BUILD_DATE := $(shell date +%Y-%m-%d) 6 | export BUILD_VERSION := $(shell date +%y%m) 7 | export BUILD_TYPE ?= stable 8 | export ICINGA2_VERSION ?= $(shell hooks/latest-version.sh) 9 | export CERT_SERVICE_TYPE ?= stable 10 | export CERT_SERVICE_VERSION ?= 0.20.0 11 | 12 | export BUILD_IMAGE ?= ${DOCKER_NAME_SPACE}/icinga2:${DOCKER_VERSION}-base 13 | 14 | 15 | .PHONY: build shell run exec start stop clean 16 | 17 | default: build 18 | 19 | build: base-build master-build satellite-build 20 | 21 | base-build: 22 | @hooks/build 23 | 24 | master-build: 25 | @hooks/build master 26 | 27 | satellite-build: 28 | @hooks/build satellite 29 | 30 | base-shell: 31 | @hooks/shell base 32 | 33 | master-shell: 34 | @hooks/shell master 35 | 36 | satellite-shell: 37 | @hooks/shell satellite 38 | 39 | run: 40 | @hooks/run 41 | 42 | exec: 43 | @hooks/exec 44 | 45 | start: 46 | @hooks/start 47 | 48 | stop: 49 | @hooks/stop 50 | 51 | clean: 52 | @hooks/clean 53 | 54 | compose-file: 55 | @hooks/compose-file 56 | 57 | publish-base: 58 | @hooks/publish 59 | 60 | linter: 61 | @tests/linter.sh 62 | 63 | integration_test: 64 | @tests/integration_test.sh 65 | 66 | test: linter integration_test 67 | -------------------------------------------------------------------------------- /build/check_mem: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # set script name 4 | SCRIPT=$(basename ${BASH_SOURCE[0]}) 5 | 6 | # set default values 7 | opt_memory_warning=95 8 | opt_memory_critical=98 9 | opt_swap_warning=95 10 | opt_swap_critical=98 11 | 12 | # help function 13 | function usage { 14 | echo -e "Help for ${SCRIPT}\n" 15 | echo -e "Basic usage: ${SCRIPT} -w {warning} -c {critical} -W {warning} -C {critical}\n" 16 | echo -e "Command switches are optional, default values for warning is 95% and critical is 98%" 17 | echo -e "-w - Sets warning value for memory usage. Default is 95%" 18 | echo -e "-c - Sets critical value for memory usage. Default is 98%" 19 | echo -e "-W - Sets warning value for swap usage. Default is 95%" 20 | echo -e "-C - Sets critical value for swap usage. Default is 98%" 21 | echo -e "-h - Displays this help message\n" 22 | echo -e "Example: ${SCRIPT} -w 80 -c 90 -W 40 -C 60\n" 23 | exit 0 24 | } 25 | 26 | # regex to check is OPTARG an integer 27 | re='^[0-9]+$' 28 | 29 | while getopts :w:c:W:C:h FLAG; do 30 | case ${FLAG} in 31 | w) 32 | if ! [[ ${OPTARG} =~ ${re} ]] 33 | then 34 | echo "ERROR: warning value for memory usage is not a number" >&2 35 | exit 1 36 | else 37 | opt_memory_warning=${OPTARG} 38 | fi 39 | ;; 40 | c) 41 | if ! [[ ${OPTARG} =~ ${re} ]] 42 | then 43 | echo "ERROR: critical value for memory usage is not a number" >&2 44 | exit 1 45 | else 46 | opt_memory_critical=${OPTARG} 47 | fi 48 | ;; 49 | W) 50 | if ! [[ ${OPTARG} =~ ${re} ]] 51 | then 52 | echo "ERROR: warning value for swap usage is not a number" >&2 53 | exit 1 54 | else 55 | opt_swap_warning=${OPTARG} 56 | fi 57 | ;; 58 | C) 59 | if ! [[ ${OPTARG} =~ ${re} ]] 60 | then 61 | echo "ERROR: critical value for swap usage is not a number" >&2 62 | exit 1 63 | else 64 | opt_swap_critical=${OPTARG} 65 | fi 66 | ;; 67 | h) 68 | usage 69 | ;; 70 | \?) 71 | echo -e "\nOption - ${OPTARG} not allowed.\n" 72 | usage 73 | exit 2 74 | ;; 75 | esac 76 | done 77 | 78 | shift $((OPTIND-1)) 79 | 80 | if [[ -e /proc/meminfo ]] 81 | then 82 | array=( $(cat /proc/meminfo | \ 83 | egrep 'MemTotal|MemFree|Buffers|Cached|SwapTotal|SwapFree' | \ 84 | awk '{print $1 " " $2}' | \ 85 | tr '\n' ' ' | \ 86 | tr -d ':' | \ 87 | awk '{ printf("%i %i %i %i %i %i %i", $2, $4, $6, $8, $10, $12, $14) }') ) 88 | 89 | memory_total_k=${array[0]} 90 | memory_total_b=$((${memory_total_k}*1024)) 91 | memory_free_k=${array[1]} 92 | memory_free_b=$((${memory_free_k}*1024)) 93 | memory_buffer_k=${array[2]} 94 | memory_buffer_b=$((${memory_buffer_k}*1024)) 95 | memory_cached_k=${array[3]} 96 | memory_cached_b=$((${memory_cached_k}*1024)) 97 | memory_total_m=$((${memory_total_k}/1024)) 98 | memory_free_m=$((${memory_free_k}/1024)) 99 | memory_buffer_m=$((${memory_buffer_k}/1024)) 100 | memory_cached_m=$((${memory_cached_k}/1024)) 101 | memory_used_b=$((${memory_total_b}-${memory_free_b}-${memory_buffer_b}-${memory_cached_b})) 102 | memory_used_m=$((${memory_total_m}-${memory_free_m}-${memory_buffer_m}-${memory_cached_m})) 103 | memory_used_percent=$(((${memory_used_b}*100)/${memory_total_b})) 104 | 105 | swap_total_k=${array[5]} 106 | swap_total_b=$((${swap_total_k}*1024)) 107 | swap_free_k=${array[6]} 108 | swap_free_b=$((${swap_free_k}*1024)) 109 | swap_used_k=$((${swap_total_k}-${swap_free_k})) 110 | swap_used_b=$((${swap_used_k}*1024)) 111 | swap_total_m=$((${swap_total_k}/1024)) 112 | swap_free_m=$((${swap_free_k}/1024)) 113 | swap_used_m=$((${swap_total_m}-${swap_free_m})) 114 | 115 | swap_used_percent=0 116 | 117 | if [[ ${swap_total_k} -gt 0 ]] 118 | then 119 | swap_used_percent=$(((${swap_used_k}*100)/${swap_total_k})) 120 | fi 121 | 122 | message="swap - size: ${swap_total_m} MB, used: ${swap_used_m} MB, used percent: ${swap_used_percent}%
" 123 | message="${message}memory - size: ${memory_total_m} MB, used: ${memory_used_m} MB, used percent: ${memory_used_percent}%" 124 | message="${message} |" 125 | message="${message} MEM_TOTAL=${memory_total_b};;;; MEM_USED=${memory_used_b};;;; MEM_CACHED=${memory_cached_b};;;; MEM_BUFFER=${memory_buffer_b};;;;" 126 | message="${message} SWAP_TOTAL=${swap_total_b};;;; SWAP_USED=${swap_used_b};;;;" 127 | 128 | echo -e "${message}" 129 | 130 | if [[ ${memory_used_percent} -ge ${opt_memory_critical} ]] || [[ ${swap_used_percent} -ge ${opt_swap_critical} ]] 131 | then 132 | $(exit 2) 133 | elif [[ ${memory_used_percent} -ge ${opt_memory_warning} ]] || [[ ${swap_used_percent} -ge ${opt_swap_warning} ]] 134 | then 135 | $(exit 1) 136 | else 137 | $(exit 0) 138 | fi 139 | 140 | else 141 | echo -e "UNKNOWN - /proc/meminfo is not available" 142 | $(exit 3) 143 | fi 144 | -------------------------------------------------------------------------------- /build/check_ssl_observatory: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /usr/lib/nagios/plugins/utils.sh 4 | 5 | # httpobs --zero github.com 6 | 7 | unknown() { 8 | printf '%s UNKNOWN%s: %s\n' "$1" 9 | exit ${STATE_UNKNOWN} 10 | } 11 | 12 | 13 | while true; do 14 | 15 | case "$1" in 16 | ######################################## 17 | # Options with arguments 18 | -H|--host) 19 | if [ $# -gt 1 ]; then 20 | HOST="$2" 21 | shift 2 22 | else 23 | unknown "-H,--host requires an argument" 24 | fi 25 | ;; 26 | ######################################## 27 | # Special 28 | --) 29 | shift 30 | break 31 | ;; 32 | -*) 33 | unknown "invalid option: ${1}" 34 | ;; 35 | *) 36 | if [ -n "$1" ] ; then 37 | unknown "invalid option: ${1}" 38 | fi 39 | break 40 | ;; 41 | 42 | esac 43 | done 44 | 45 | 46 | # httpobs --hidden ${HOST} 47 | 48 | exit 1 49 | -------------------------------------------------------------------------------- /compose/config/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | worker_processes 1; 3 | 4 | error_log /dev/stdout notice; 5 | 6 | daemon off; 7 | pid run/nginx.pid; 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | http { 14 | include mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; 18 | 19 | map $http_user_agent $ignore_ua { 20 | default 1; 21 | "ELB-HealthChecker/1.0" 0; 22 | "ELB-HealthChecker/2.0" 0; 23 | } 24 | 25 | access_log /dev/stdout main; 26 | 27 | sendfile on; 28 | 29 | keepalive_timeout 300; 30 | send_timeout 600; 31 | 32 | gzip on; 33 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 34 | 35 | include /etc/nginx/conf.d/*.conf; 36 | 37 | server { 38 | listen *:80 default_server; 39 | server_name _; 40 | 41 | log_not_found off; 42 | access_log off; 43 | error_log off; 44 | 45 | # we want an permantent redirect to https 46 | # 47 | if ($ssl_protocol = "") { 48 | return 301 https://$host$request_uri; 49 | } 50 | } 51 | 52 | server { 53 | listen *:443 ssl http2; 54 | server_name _; 55 | 56 | resolver 127.0.0.11 valid=2; 57 | 58 | ssl on; 59 | ssl_certificate /etc/nginx/secure/localhost/cert.pem; 60 | ssl_certificate_key /etc/nginx/secure/localhost/key.pem; 61 | ssl_dhparam /etc/nginx/secure/localhost/dh.pem; 62 | 63 | # only this domain 64 | add_header Strict-Transport-Security "max-age=31536000"; 65 | 66 | # apply also on subdomains 67 | add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; 68 | 69 | include conf.d/ssl.conf; 70 | include modules.d/00-health_check.conf; 71 | include modules.d/00-restrictions.conf; 72 | 73 | location = / { 74 | return 301 https://$host/icinga; 75 | } 76 | 77 | #location /icinga { 78 | # log_not_found off; 79 | # access_log /dev/stdout; 80 | # error_log /dev/stdout; 81 | # 82 | # add_header X-Backend "icingaweb2"; 83 | # 84 | # proxy_pass http://icingaweb2; 85 | # proxy_set_header Host $host; 86 | # proxy_set_header X-Real-IP $remote_addr; 87 | # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 88 | # proxy_set_header X-Forwarded-Proto $scheme; 89 | #} 90 | 91 | location /cert-service { 92 | log_not_found off; 93 | access_log /dev/stdout; 94 | error_log /dev/stdout; 95 | 96 | add_header X-Backend "icinga-cert-service"; 97 | 98 | proxy_pass http://icinga2-master:8080/; 99 | proxy_set_header Host $host; 100 | proxy_set_header X-Real-IP $remote_addr; 101 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 102 | proxy_set_header X-Forwarded-Proto $scheme; 103 | } 104 | 105 | #location /grafana/ { 106 | # 107 | # log_not_found off; 108 | # access_log off; 109 | # error_log off; 110 | # 111 | # add_header X-Backend "grafana"; 112 | # 113 | # proxy_pass http://grafana:3000/; 114 | # 115 | # proxy_set_header Host $host; 116 | # proxy_set_header X-Real-IP $remote_addr; 117 | # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 118 | # proxy_set_header X-Forwarded-Proto $scheme; 119 | #} 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /compose/database.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | database: 7 | image: bodsch/docker-mariadb:10.3.12 8 | container_name: database 9 | hostname: database.matrix.lan 10 | environment: 11 | - MARIADB_SYSTEM_USER=root 12 | - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} 13 | networks: 14 | - database 15 | # volumes: 16 | # - database:/srv 17 | -------------------------------------------------------------------------------- /compose/grafana.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | grafana: 7 | image: bodsch/docker-grafana 8 | restart: always 9 | container_name: grafana 10 | hostname: grafana.matrix.lan 11 | ports: 12 | - 3000:3000 13 | environment: 14 | - URL_PATH 15 | - LOG_LEVEL 16 | - ROUTER_LOGGING 17 | volumes: 18 | - ./import/provisioning:/etc/grafana/provisioning:ro 19 | - ./import/dashboards:/var/lib/grafana/dashboards:ro 20 | links: 21 | # - graphite.matrix.lan 22 | - influx:influx.matrix.lan 23 | depends_on: 24 | # - graphite 25 | - influx 26 | networks: 27 | - frontend 28 | - backend 29 | - database 30 | -------------------------------------------------------------------------------- /compose/graphite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | graphite: 7 | restart: always 8 | image: bodsch/docker-graphite:1.1.5 9 | container_name: graphite.matrix.lan 10 | hostname: graphite 11 | networks: 12 | - backend 13 | -------------------------------------------------------------------------------- /compose/head.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | networks: 5 | frontend: 6 | backend: 7 | database: 8 | 9 | #volumes: 10 | # database: 11 | # driver: local 12 | # icinga: 13 | # driver: local 14 | # satellite-1: 15 | # driver: local 16 | # satellite-2: 17 | # driver: local 18 | # 19 | -------------------------------------------------------------------------------- /compose/icingaweb2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | # icingaweb2 6 | # 7 | icingaweb2: 8 | image: bodsch/docker-icingaweb2 9 | container_name: icingaweb2 10 | hostname: icingaweb2.matrix.lan 11 | ports: 12 | - 80 13 | environment: 14 | - MYSQL_HOST=database 15 | - MYSQL_ROOT_USER=root 16 | - MYSQL_ROOT_PASS=${MARIADB_ROOT_PASSWORD} 17 | - IDO_DATABASE_NAME=icinga2core 18 | - IDO_PASSWORD=${IDO_PASSWORD} 19 | - ICINGA2_MASTER=icinga2-master.matrix.lan 20 | - ICINGA2_CMD_API_USER=root 21 | - ICINGA2_CMD_API_PASS=icinga 22 | - ICINGAWEB2_USERS=icinga:icinga,foo:bar 23 | - ICINGAWEB_DIRECTOR=false 24 | env_file: 25 | - ${PWD}/.env 26 | links: 27 | - icinga2-master:icinga2-master.matrix.lan 28 | - database 29 | networks: 30 | - database 31 | - frontend 32 | - backend 33 | -------------------------------------------------------------------------------- /compose/import/dashboards/QA-Test.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "editable": true, 16 | "gnetId": null, 17 | "graphTooltip": 0, 18 | "id": 4, 19 | "links": [], 20 | "panels": [ 21 | { 22 | "aliasColors": {}, 23 | "bars": false, 24 | "dashLength": 10, 25 | "dashes": false, 26 | "datasource": "-- Grafana --", 27 | "fill": 1, 28 | "gridPos": { 29 | "h": 9, 30 | "w": 24, 31 | "x": 0, 32 | "y": 0 33 | }, 34 | "id": 2, 35 | "legend": { 36 | "avg": false, 37 | "current": false, 38 | "max": false, 39 | "min": false, 40 | "show": true, 41 | "total": false, 42 | "values": false 43 | }, 44 | "lines": true, 45 | "linewidth": 1, 46 | "links": [], 47 | "nullPointMode": "null", 48 | "paceLength": 10, 49 | "percentage": false, 50 | "pointradius": 2, 51 | "points": false, 52 | "renderer": "flot", 53 | "seriesOverrides": [], 54 | "stack": false, 55 | "steppedLine": false, 56 | "thresholds": [], 57 | "timeFrom": null, 58 | "timeRegions": [], 59 | "timeShift": null, 60 | "title": "QA Test", 61 | "tooltip": { 62 | "shared": true, 63 | "sort": 0, 64 | "value_type": "individual" 65 | }, 66 | "transparent": true, 67 | "type": "graph", 68 | "xaxis": { 69 | "buckets": null, 70 | "mode": "time", 71 | "name": null, 72 | "show": true, 73 | "values": [] 74 | }, 75 | "yaxes": [ 76 | { 77 | "format": "short", 78 | "label": null, 79 | "logBase": 1, 80 | "max": null, 81 | "min": null, 82 | "show": true 83 | }, 84 | { 85 | "format": "short", 86 | "label": null, 87 | "logBase": 1, 88 | "max": null, 89 | "min": null, 90 | "show": true 91 | } 92 | ], 93 | "yaxis": { 94 | "align": false, 95 | "alignLevel": null 96 | } 97 | } 98 | ], 99 | "schemaVersion": 18, 100 | "style": "dark", 101 | "tags": [], 102 | "templating": { 103 | "list": [] 104 | }, 105 | "time": { 106 | "from": "now-6h", 107 | "to": "now" 108 | }, 109 | "timepicker": { 110 | "refresh_intervals": [ 111 | "5s", 112 | "10s", 113 | "30s", 114 | "1m", 115 | "5m", 116 | "15m", 117 | "30m", 118 | "1h", 119 | "2h", 120 | "1d" 121 | ], 122 | "time_options": [ 123 | "5m", 124 | "15m", 125 | "1h", 126 | "6h", 127 | "12h", 128 | "24h", 129 | "2d", 130 | "7d", 131 | "30d" 132 | ] 133 | }, 134 | "timezone": "", 135 | "title": "QA Test", 136 | "uid": "qa-test", 137 | "version": 2 138 | } 139 | -------------------------------------------------------------------------------- /compose/import/dashboards/icinga2-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "description": "Show all metrics from a Icinga2 service or host", 16 | "editable": true, 17 | "gnetId": null, 18 | "graphTooltip": 0, 19 | "id": 1, 20 | "iteration": 1549642691124, 21 | "links": [], 22 | "panels": [ 23 | { 24 | "aliasColors": {}, 25 | "bars": false, 26 | "dashLength": 10, 27 | "dashes": false, 28 | "datasource": "Icinga2", 29 | "fill": 1, 30 | "gridPos": { 31 | "h": 7, 32 | "w": 24, 33 | "x": 0, 34 | "y": 0 35 | }, 36 | "id": 1, 37 | "legend": { 38 | "alignAsTable": false, 39 | "avg": false, 40 | "current": false, 41 | "max": false, 42 | "min": false, 43 | "rightSide": false, 44 | "show": true, 45 | "total": false, 46 | "values": false 47 | }, 48 | "lines": true, 49 | "linewidth": 1, 50 | "links": [], 51 | "nullPointMode": "null", 52 | "percentage": false, 53 | "pointradius": 1, 54 | "points": false, 55 | "renderer": "flot", 56 | "seriesOverrides": [], 57 | "spaceLength": 10, 58 | "stack": false, 59 | "steppedLine": false, 60 | "targets": [ 61 | { 62 | "alias": "$tag_metric", 63 | "dsType": "influxdb", 64 | "groupBy": [ 65 | { 66 | "params": [ 67 | "$__interval" 68 | ], 69 | "type": "time" 70 | }, 71 | { 72 | "params": [ 73 | "metric" 74 | ], 75 | "type": "tag" 76 | }, 77 | { 78 | "params": [ 79 | "none" 80 | ], 81 | "type": "fill" 82 | } 83 | ], 84 | "measurement": "/^$command$/", 85 | "orderByTime": "ASC", 86 | "policy": "default", 87 | "refId": "A", 88 | "resultFormat": "time_series", 89 | "select": [ 90 | [ 91 | { 92 | "params": [ 93 | "value" 94 | ], 95 | "type": "field" 96 | }, 97 | { 98 | "params": [], 99 | "type": "mean" 100 | } 101 | ] 102 | ], 103 | "tags": [ 104 | { 105 | "key": "hostname", 106 | "operator": "=~", 107 | "value": "/^$hostname$/" 108 | }, 109 | { 110 | "condition": "AND", 111 | "key": "service", 112 | "operator": "=~", 113 | "value": "/^$service$/" 114 | } 115 | ] 116 | } 117 | ], 118 | "thresholds": [], 119 | "timeFrom": null, 120 | "timeRegions": [], 121 | "timeShift": null, 122 | "title": "$service", 123 | "tooltip": { 124 | "shared": true, 125 | "sort": 1, 126 | "value_type": "individual" 127 | }, 128 | "type": "graph", 129 | "xaxis": { 130 | "buckets": null, 131 | "mode": "time", 132 | "name": null, 133 | "show": true, 134 | "values": [] 135 | }, 136 | "yaxes": [ 137 | { 138 | "format": "short", 139 | "label": null, 140 | "logBase": 1, 141 | "max": null, 142 | "min": null, 143 | "show": true 144 | }, 145 | { 146 | "format": "short", 147 | "label": null, 148 | "logBase": 1, 149 | "max": null, 150 | "min": null, 151 | "show": false 152 | } 153 | ], 154 | "yaxis": { 155 | "align": false, 156 | "alignLevel": null 157 | } 158 | } 159 | ], 160 | "schemaVersion": 16, 161 | "style": "dark", 162 | "tags": [ 163 | "Icinga2", 164 | "influxdb" 165 | ], 166 | "templating": { 167 | "list": [ 168 | { 169 | "current": { 170 | "text": "null", 171 | "value": "null" 172 | }, 173 | "hide": 2, 174 | "label": null, 175 | "name": "hostname", 176 | "options": [ 177 | { 178 | "text": "null", 179 | "value": "null" 180 | } 181 | ], 182 | "query": "null", 183 | "skipUrlSync": false, 184 | "type": "constant" 185 | }, 186 | { 187 | "current": { 188 | "text": "null", 189 | "value": "null" 190 | }, 191 | "hide": 2, 192 | "label": null, 193 | "name": "service", 194 | "options": [ 195 | { 196 | "text": "null", 197 | "value": "null" 198 | } 199 | ], 200 | "query": "null", 201 | "skipUrlSync": false, 202 | "type": "constant" 203 | }, 204 | { 205 | "current": { 206 | "text": "null", 207 | "value": "null" 208 | }, 209 | "hide": 2, 210 | "label": null, 211 | "name": "command", 212 | "options": [ 213 | { 214 | "text": "null", 215 | "value": "null" 216 | } 217 | ], 218 | "query": "null", 219 | "skipUrlSync": false, 220 | "type": "constant" 221 | } 222 | ] 223 | }, 224 | "time": { 225 | "from": "now-6h", 226 | "to": "now" 227 | }, 228 | "timepicker": { 229 | "refresh_intervals": [ 230 | "5s", 231 | "10s", 232 | "30s", 233 | "1m", 234 | "5m", 235 | "15m", 236 | "30m", 237 | "1h", 238 | "2h", 239 | "1d" 240 | ], 241 | "time_options": [ 242 | "5m", 243 | "15m", 244 | "1h", 245 | "6h", 246 | "12h", 247 | "24h", 248 | "2d", 249 | "7d", 250 | "30d" 251 | ] 252 | }, 253 | "timezone": "", 254 | "title": "icinga2-default", 255 | "uid": "icinga2-default", 256 | "version": 1 257 | } 258 | -------------------------------------------------------------------------------- /compose/import/host_object_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": [ "satellite-host" ], 3 | "attrs": { 4 | "command_endpoint": "%FQDN%", 5 | "zone": "%FQDN%", 6 | "enable_notifications": true, 7 | "groups": ["icinga-satellites"], 8 | "max_check_attempts": "2", 9 | "check_interval": "30", 10 | "retry_interval": "10", 11 | "vars": { 12 | "os": "Docker", 13 | "remote_endpoint": "%FQDN%", 14 | "satellite": "true", 15 | "memory": "true" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /compose/import/host_object_data_icinga2-satellite-2.matrix.lan.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": [ "satellite-host" ], 3 | "attrs": { 4 | "command_endpoint": "%FQDN%", 5 | "zone": "%FQDN%", 6 | "enable_notifications": true, 7 | "groups": ["icinga-satellites"], 8 | "max_check_attempts": "2", 9 | "check_interval": "30", 10 | "retry_interval": "10", 11 | "vars": { 12 | "os": "Docker", 13 | "remote_endpoint": "%FQDN%", 14 | "satellite": "true", 15 | "qa": "true", 16 | "date": "2019-02-13", 17 | "memory": "true", 18 | "file_age": { 19 | "/host/tmp/backup": { 20 | "warning_time": 76800, 21 | "critical_time": 128000 22 | } 23 | }, 24 | "http_vhosts": { 25 | "/": { 26 | "http_uri": "/", 27 | "http_vhost": "%FQDN%", 28 | "http_address": "%FQDN%" 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /compose/import/host_object_data_icinga2-satellite-2.matrix.lan_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates": [ "satellite-host" ], 3 | "attrs": { 4 | "command_endpoint": "icinga2-satellite-2.matrix.lan", 5 | "zone": "icinga2-satellite-2.matrix.lan", 6 | "enable_notifications": true, 7 | "groups": ["icinga-satellites"], 8 | "max_check_attempts": "2", 9 | "check_interval": "30", 10 | "retry_interval": "10", 11 | "vars": { 12 | "os": "Docker", 13 | "remote_endpoint": "icinga2-satellite-2.matrix.lan", 14 | "satellite": "true", 15 | "qa": "true", 16 | "date": "2019-02-13", 17 | "notification": "true", 18 | "memory": "true", 19 | "file_age": { 20 | "/tmp/backup": { 21 | "warning_time": 76800, 22 | "critical_time": 128000 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /compose/import/provisioning/dashboards/dashboards.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | orgId: 1 6 | folder: '' 7 | type: file 8 | disableDeletion: false 9 | updateIntervalSeconds: 10 #how often Grafana will scan for changed dashboards 10 | options: 11 | path: /var/lib/grafana/dashboards 12 | -------------------------------------------------------------------------------- /compose/import/provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # list of datasources that should be deleted from the database 5 | deleteDatasources: 6 | - name: Icinga2 7 | orgId: 1 8 | 9 | # list of datasources to insert/update depending 10 | # whats available in the database 11 | ## This is for swarm, url is: stackname_servicename 12 | datasources: 13 | - name: Icinga2 14 | type: influxdb 15 | access: proxy 16 | database: icinga2 17 | user: icinga2 18 | password: w7uK6nfcxR6ZBtZC 19 | url: http://influx:8086 20 | editable: true 21 | jsonData: 22 | timeInterval: "15s" 23 | 24 | - name: graphite 25 | type: graphite 26 | isDefault: true 27 | access: proxy 28 | url: http://graphite:8080 29 | editable: true 30 | jsonData: 31 | graphiteVersion: "1.1" 32 | -------------------------------------------------------------------------------- /compose/import/provisioning/notifiers/notifier.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # http://docs.grafana.org/administration/provisioning/#provisioning-grafana 5 | 6 | #delete_notifiers: 7 | # - name: notification-channel-1 8 | # - name: notification-channel-2 9 | -------------------------------------------------------------------------------- /compose/influxdb.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | influx: 6 | restart: always 7 | image: influxdb:1.7-alpine 8 | container_name: influx 9 | hostname: influx.matrix.lan 10 | environment: 11 | - INFLUXDB_DB 12 | - INFLUXDB_HTTP_AUTH_ENABLED 13 | - INFLUXDB_ADMIN_USER 14 | - INFLUXDB_ADMIN_PASSWORD 15 | - INFLUXDB_USER 16 | - INFLUXDB_USER_PASSWORD 17 | networks: 18 | - backend 19 | -------------------------------------------------------------------------------- /compose/master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | # the Icinga2 Master 6 | # includes a certificate service to create and provide a icinga certificate 7 | icinga2-master: 8 | #image: ${DOCKER_NAME_SPACE}/docker-icinga2:${DOCKER_VERSION}-master 9 | build: 10 | context: .. 11 | dockerfile: Dockerfile.master 12 | args: 13 | - BUILD_IMAGE 14 | - BUILD_DATE 15 | - BUILD_VERSION 16 | - ICINGA2_VERSION 17 | - CERT_SERVICE_TYPE 18 | - CERT_SERVICE_VERSION 19 | container_name: icinga2-master 20 | hostname: icinga2-master.matrix.lan 21 | restart: always 22 | privileged: true 23 | ports: 24 | - 5665:5665 25 | - 8080 26 | environment: 27 | - ICINGA2_API_USERS=root:icinga,dashing:dashing,cert:foo-bar 28 | - DEBUG 29 | - LOG_LEVEL 30 | - MYSQL_HOST=database 31 | - MYSQL_ROOT_USER=${MARIADB_SYSTEM_USER} 32 | - MYSQL_ROOT_PASS=${MARIADB_ROOT_PASSWORD} 33 | - IDO_PASSWORD 34 | # environment variables for the certificates service 35 | - ICINGA2_MASTER 36 | - BASIC_AUTH_USER 37 | - BASIC_AUTH_PASS 38 | # rest api 39 | - CERT_SERVICE_BA_USER 40 | - CERT_SERVICE_BA_PASSWORD 41 | - CERT_SERVICE_API_USER 42 | - CERT_SERVICE_API_PASSWORD 43 | - CERT_SERVICE_SERVER 44 | - CERT_SERVICE_PORT 45 | - CERT_SERVICE_PATH 46 | # # graphite 47 | # - CARBON_HOST 48 | # - CARBON_PORT 49 | # # influxdb 50 | # - INFLUXDB_HOST 51 | # - INFLUXDB_USER 52 | # - INFLUXDB_PASS 53 | # - INFLUXDB_DB 54 | # # 55 | - DEMO_DATA 56 | - TICKET_SALT 57 | # env_file: 58 | # - ${PWD}/.env 59 | links: 60 | - database:database.matrix.lan 61 | # - influx:influx.matrix.lan 62 | cap_add: 63 | - NET_ADMIN 64 | - SYS_ADMIN 65 | # cap_drop: 66 | # - NET_ADMIN 67 | # - SYS_ADMIN 68 | networks: 69 | - database 70 | - backend 71 | # volumes: 72 | # - icinga:/var/lib/icinga2 73 | -------------------------------------------------------------------------------- /compose/nginx.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | nginx: 6 | restart: always 7 | image: bodsch/docker-nginx 8 | container_name: nginx 9 | hostname: nginx.matrix.lan 10 | ports: 11 | - 80:80 12 | - 443:443 13 | depends_on: 14 | - icinga2-master 15 | # - icingaweb2 16 | links: 17 | - icinga2-master 18 | # - icingaweb2:icingaweb2.matrix.lan 19 | volumes: 20 | - ./ssl/cert.pem:/etc/nginx/secure/localhost/cert.pem:ro 21 | - ./ssl/key.pem:/etc/nginx/secure/localhost/key.pem:ro 22 | - ./ssl/dh.pem:/etc/nginx/secure/localhost/dh.pem:ro 23 | - ./config/nginx.conf:/etc/nginx/nginx.conf:ro 24 | networks: 25 | - frontend 26 | - backend 27 | -------------------------------------------------------------------------------- /compose/satellite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | icinga2-satellite-1: 7 | build: 8 | context: .. 9 | dockerfile: Dockerfile.satellite 10 | args: 11 | - BUILD_IMAGE=${BUILD_IMAGE} 12 | - BUILD_DATE=${BUILD_DATE} 13 | - BUILD_VERSION=${BUILD_VERSION} 14 | - ICINGA2_VERSION=${ICINGA2_VERSION} 15 | container_name: icinga2-satellite-1 16 | hostname: icinga2-satellite-1.matrix.lan 17 | restart: always 18 | privileged: true 19 | environment: 20 | - DEBUG 21 | - ICINGA2_LOGLEVEL 22 | - ICINGA2_MASTER 23 | - ICINGA2_PARENT 24 | - TICKET_SALT 25 | - CERT_SERVICE_BA_USER 26 | - CERT_SERVICE_BA_PASSWORD 27 | - CERT_SERVICE_API_USER 28 | - CERT_SERVICE_API_PASSWORD 29 | - CERT_SERVICE_SERVER 30 | - CERT_SERVICE_PORT 31 | - CERT_SERVICE_PATH 32 | volumes: 33 | - /proc:/host/proc:ro 34 | - /sys:/host/sys:ro 35 | - /sys:/sys:ro 36 | - /dev:/dev:ro 37 | links: 38 | - icinga2-master:icinga2-master.matrix.lan 39 | - nginx:nginx.matrix.lan 40 | cap_add: 41 | - NET_ADMIN 42 | - SYS_ADMIN 43 | networks: 44 | - backend 45 | # volumes: 46 | # - satellite-1:/var/lib/icinga2 47 | 48 | # icinga2-satellite-2: 49 | # build: 50 | # context: .. 51 | # dockerfile: Dockerfile.satellite 52 | # args: 53 | # - BUILD_IMAGE=${BUILD_IMAGE} 54 | # - BUILD_DATE=${BUILD_DATE} 55 | # - BUILD_VERSION=${BUILD_VERSION} 56 | # - ICINGA2_VERSION=${ICINGA2_VERSION} 57 | # container_name: icinga2-satellite-2 58 | # hostname: icinga2-satellite-2.matrix.lan 59 | # restart: always 60 | # privileged: true 61 | # environment: 62 | # - DEBUG 63 | # - DEVELOPMENT_MODUS 64 | # - ICINGA2_LOGLEVEL 65 | # - ICINGA2_MASTER 66 | # - ICINGA2_PARENT 67 | # - TICKET_SALT 68 | # - CERT_SERVICE_BA_USER 69 | # - CERT_SERVICE_BA_PASSWORD 70 | # - CERT_SERVICE_API_USER 71 | # - CERT_SERVICE_API_PASSWORD 72 | # - CERT_SERVICE_SERVER 73 | # - CERT_SERVICE_PORT 74 | # - CERT_SERVICE_PATH 75 | # volumes: 76 | # - ../import:/import:ro 77 | # - /proc:/host/proc:ro 78 | # - /sys:/host/sys:ro 79 | # - /sys:/sys:ro 80 | # - /dev:/dev:ro 81 | # links: 82 | # - icinga2-master:icinga2-master.matrix.lan 83 | # cap_add: 84 | # - NET_ADMIN 85 | # - SYS_ADMIN 86 | # networks: 87 | # - backend 88 | ## volumes: 89 | ## - satellite-2:/var/lib/icinga2 90 | # 91 | # icinga2-satellite-3: 92 | # build: 93 | # context: .. 94 | # dockerfile: Dockerfile.satellite 95 | # args: 96 | # - BUILD_IMAGE=${BUILD_IMAGE} 97 | # - BUILD_DATE=${BUILD_DATE} 98 | # - BUILD_VERSION=${BUILD_VERSION} 99 | # - ICINGA2_VERSION=${ICINGA2_VERSION} 100 | # container_name: icinga2-satellite-3 101 | # hostname: icinga2-satellite-3.matrix.lan 102 | # restart: always 103 | # privileged: true 104 | # environment: 105 | # - DEBUG 106 | # - ICINGA2_LOGLEVEL 107 | # - ICINGA2_MASTER 108 | # - ICINGA2_PARENT 109 | # - TICKET_SALT 110 | # - CERT_SERVICE_BA_USER 111 | # - CERT_SERVICE_BA_PASSWORD 112 | # - CERT_SERVICE_API_USER 113 | # - CERT_SERVICE_API_PASSWORD 114 | # - CERT_SERVICE_SERVER 115 | # - CERT_SERVICE_PORT 116 | # - CERT_SERVICE_PATH 117 | # links: 118 | # - icinga2-master:icinga2-master.matrix.lan 119 | # cap_add: 120 | # - NET_ADMIN 121 | # - SYS_ADMIN 122 | # networks: 123 | # - backend 124 | # 125 | -------------------------------------------------------------------------------- /compose/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDozCCAougAwIBAgIJALtPIdJ3TvOIMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV 3 | BAYTAkRFMRAwDgYDVQQIDAdIYW1idXJnMRAwDgYDVQQHDAdIYW1idXJnMSEwHwYD 4 | VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9z 5 | dDAeFw0xODA4MjAwODM2MjhaFw0xOTA4MjAwODM2MjhaMGgxCzAJBgNVBAYTAkRF 6 | MRAwDgYDVQQIDAdIYW1idXJnMRAwDgYDVQQHDAdIYW1idXJnMSEwHwYDVQQKDBhJ 7 | bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIw 8 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBQyX42gJDn3HK0grRW10fYhbKb 9 | y5rJRVizrXGQXDU+oQEKBH1tMnQdyYbHD0PKzdzTU4SUnlGXRfr7MOWISZ1H8tjQ 10 | EYg/JI/MWBPUnI4kFtHAdjSi91MnrEjmS4I4eBJnJYqN/07oiwmpzmqrBTDQ1ZbF 11 | 17+jSFfK7ZHLbHs9HuPFA2Ws3atxH9OMjH6gK0ORbnO7dbyXfHWWTmrHg21pgLTH 12 | 4jlBlzJSwXQ8+6oPwD3Bl9uDPTvpTKrJ0jEC+8GMosU7uCVO88lK61zVWWdYSWDi 13 | /GAhqbJBsHbejiS0g2KWKSf6Ed/c3bIHVcTB3q9kDR3y3/hS8NBh22PDEF8CAwEA 14 | AaNQME4wHQYDVR0OBBYEFPS5vhkV8xAmlwYIiw7i8ebwHOjgMB8GA1UdIwQYMBaA 15 | FPS5vhkV8xAmlwYIiw7i8ebwHOjgMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL 16 | BQADggEBAGsyObFBllTtdHqOf9Y4XiZr4E/dh39ET8Kdb4LSdPiOdtG3Y4gFhsD2 17 | 1c/cjYoc8jQhI7W5ukqRVlIlsVPimvqo0WJK2MJrooyI4kj2Y0AueA2ArGVaoSOr 18 | RUMUwNH99P5kGuJjyMHpbh1LYCMdFzREW1rFOU0ieAW8ujv35wZxLMuigrljvgND 19 | 9z35D0OTWUeO42kD7FovJqa8zRhh4OHsJNs327WGbrDHvkIaj4vvQiT7ijOeHg9o 20 | HlX8kXhBwNoGlhPTxZOFzLS7Q5TFuaSpNDyTkJf67+r9QodC7kR+Q6CqXFUhGqRx 21 | vPFpVE0qj5p6P2xYqjw6jmXPF1/JWMQ= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /compose/ssl/dh.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEAzEY5vhK7YfazPE8PFvmfSJeee0Ea0VWHXQVUFlB356nS+k6j7C9h 3 | AfTpdkStz7BvRbYmAuCboDehmITmwyRL88Cady1BSi3U0Ki/OT5AgCc7lVuHcjHr 4 | fEesLNmGzcVDj0a82yXHL+iIjG4JiCMOKaHD0cuTX3wiONi7yJCc/b5ANGzT9pYV 5 | 5XWa1WwU4qDwBhoZOeJB2CEjWtV4n2F0AyP+pqNxCLOHoiZ7DIcjaQ6QymT8TX/q 6 | lsbLcjHYRfme1gjCZ8/Fnsn8F9ha7pd1JwKKb6Jsp1IjARz3eQgS6rrMQgMAXsv4 7 | qNOZQ07lINe1vyZ3yo3vsjcYX4NAXGy7ewIBAg== 8 | -----END DH PARAMETERS----- 9 | -------------------------------------------------------------------------------- /compose/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAUMl+NoCQ59xy 3 | tIK0VtdH2IWym8uayUVYs61xkFw1PqEBCgR9bTJ0HcmGxw9Dys3c01OElJ5Rl0X6 4 | +zDliEmdR/LY0BGIPySPzFgT1JyOJBbRwHY0ovdTJ6xI5kuCOHgSZyWKjf9O6IsJ 5 | qc5qqwUw0NWWxde/o0hXyu2Ry2x7PR7jxQNlrN2rcR/TjIx+oCtDkW5zu3W8l3x1 6 | lk5qx4NtaYC0x+I5QZcyUsF0PPuqD8A9wZfbgz076UyqydIxAvvBjKLFO7glTvPJ 7 | Sutc1VlnWElg4vxgIamyQbB23o4ktINilikn+hHf3N2yB1XEwd6vZA0d8t/4UvDQ 8 | YdtjwxBfAgMBAAECggEALoIbCFvT4bdA17iRt10c+PIC+zu0FH3COH5TXphjxDie 9 | JSswBMkon24os2Bmb6WW/WVZ2EE8vEySDu06WPgJnXCt6QMAimuCwwfO8RTEu5c8 10 | sYMS0w3qNADvKD4RWq+fUgwBxy0p5gJUxYR8N82eFr0aOjkkQOMS9rBLnauNU4v8 11 | FhzsmjWXuhwZklxmJS6t6byUVCSthVrWDFx9jndg76P9EtTo+jSMevPyn/v7jQoF 12 | EPFAp0isObLOwUFeHcy4SaYhVh1op7qHymT3k3AlVczuqbJRUhFtjbUWFCQqJJoG 13 | fZRpzAVGKhXjTxlqGDqU6qUzTosVr2pKAoQfe0AA0QKBgQDjyUlHGParP36JJnvr 14 | +M2CiBaPopXa6SdoW5Z4+LtRMk7J3xTlgYfwb/YtFnD2lQTtm4qSgu8aUHeBxJ+e 15 | 8eFBZOTcjwqiZf4H7WiWYp5lN0bdjzhhzCnmc7Xf+4NmUrNWxEBscc0XH7EkbWKv 16 | 4XtlyjuneHBzTPsU+GKhtq3DeQKBgQDYIskYG6MvwuYj461D5TCRXoPE8fwVESqq 17 | PDvbiSFp/SDwAEsdKoMX8omWSiVRaxO8u0dCt3Prk1D2p69rY8jGa/5Ru4ShCzJ/ 18 | dgwBdna2EPyHUQM3QBvBpJ6FuYXbpjJK2Jkq4WHgMLQ4uiw6eta+VLBBiKem9JQq 19 | RFhrSlXklwKBgBkYL855XZN4J0SMzNIuUtWykGm6i6/WR9UjYexp2pkTZcKvpOmz 20 | 33oJm6FT+5XuzOAwZo/FhPntK31MYBlupFZD+0KhL5a8jcPpz7/hlXmpIVF/WcLM 21 | b0FINh065Dr9mWxRqpdH4kRN5YIR2vFtcd7A7NmCV0Eclfy1cIhIS9RhAoGBAMkS 22 | K3RzGbBwJ7wRrnoweKt0ey+4U2Sh8MgoeyM0gtJge8jq7PY4O3cG2rrnRapl7Bmz 23 | PIszsfLhvPuKamaEkR8PDqyov602hocPogGmXK/qQ5P7aPt4d5oBdLxBKOd7yOPa 24 | dzvuKyjvBmqTwFuzNZ4hmUuOPzHR7RkZNgyyPhAHAoGAGj42xQKsXMuaaEkVv/EA 25 | IiiEh83N42iJLzZ+wIzOtFgZdzMiAJbP6gSJ8wiSTHT6UvUb0esR+CVLF+XT4H/i 26 | iHvoy91UeeG1WhrQPK0GdZzl4QQq5g/X7eK4A++S2SuBopcoXBfhr3xeTuuBYIcK 27 | Csk/hQ5ONXfFHh73GMF8Cok= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /doc/assets/master-satellite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodsch/docker-icinga2/f5110537d8abf7fb155f1d1b7e7d66f2cc6e38cf/doc/assets/master-satellite.jpg -------------------------------------------------------------------------------- /doc/assets/master-satellite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodsch/docker-icinga2/f5110537d8abf7fb155f1d1b7e7d66f2cc6e38cf/doc/assets/master-satellite.png -------------------------------------------------------------------------------- /hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | set -e 7 | 8 | ICINGA2_TYPE=${1} 9 | 10 | # FROM ubuntu:19.04 11 | # FROM debian:9-slim 12 | 13 | BUILD_BASE=${BUILD_BASE:-'ubuntu:19.04'} 14 | 15 | echo "" 16 | echo " BUILD_DATE : ${BUILD_DATE}" 17 | echo " BUILD_BASE : ${BUILD_BASE}" 18 | echo " ICINGA2_VERSION : ${ICINGA2_VERSION}" 19 | [ -n "${ICINGA2_TYPE}" ] && echo " ICINGA2_TYPE : ${ICINGA2_TYPE}" 20 | [ "${ICINGA2_TYPE}" = "master" ] && echo " CERT_SERVICE_VERSION: ${CERT_SERVICE_VERSION}" 21 | echo " GIT_SHA1 : ${GIT_SHA1}" 22 | echo "" 23 | 24 | echo "build debian based" 25 | 26 | if [ -z "${ICINGA2_TYPE}" ] 27 | then 28 | docker build \ 29 | --file Dockerfile.base \ 30 | --build-arg VCS_REF="${GIT_SHA1}" \ 31 | --build-arg BUILD_BASE="${BUILD_BASE}" \ 32 | --build-arg BUILD_DATE="${BUILD_DATE}" \ 33 | --build-arg BUILD_VERSION="${BUILD_VERSION}" \ 34 | --build-arg ICINGA2_VERSION="${ICINGA2_VERSION}" \ 35 | --build-arg CERT_SERVICE_TYPE= \ 36 | --build-arg CERT_SERVICE_VERSION= \ 37 | --tag "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base" . 38 | 39 | echo "" 40 | docker images "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base" | tail -n1 41 | 42 | echo "" 43 | echo "---------------------------------------------------------------------" 44 | else 45 | 46 | echo "" 47 | echo " icinga2-${ICINGA2_TYPE} (use build base: ${BUILD_IMAGE})" 48 | echo "" 49 | 50 | if [ "${ICINGA2_TYPE}" = "master" ] 51 | then 52 | pushd build > /dev/null 53 | 54 | if [[ "${CERT_SERVICE_TYPE}" = "local" ]] 55 | then 56 | echo "use local sources" 57 | 58 | else 59 | if [[ ! -d ruby-icinga-cert-service ]] 60 | then 61 | git clone https://github.com/bodsch/ruby-icinga-cert-service.git 62 | else 63 | pushd ruby-icinga-cert-service > /dev/null 64 | git fetch --all --prune -a 65 | popd > /dev/null 66 | fi 67 | 68 | cd ruby-icinga-cert-service 69 | 70 | if [[ "${CERT_SERVICE_TYPE}" = "stable" ]] 71 | then 72 | echo "switch to stable Tag v${CERT_SERVICE_VERSION}" 73 | git checkout "tags/${CERT_SERVICE_VERSION}" 2> /dev/null 74 | elif [[ "${CERT_SERVICE_TYPE}" = "development" ]] 75 | then 76 | echo "switch to development Branch" 77 | git checkout development 2> /dev/null 78 | fi 79 | fi 80 | 81 | popd > /dev/null 82 | 83 | docker build \ 84 | --file "Dockerfile.${ICINGA2_TYPE}" \ 85 | --compress \ 86 | --cache-from "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base" \ 87 | --build-arg BUILD_IMAGE="${BUILD_IMAGE}" \ 88 | --build-arg VCS_REF="${GIT_SHA1}" \ 89 | --build-arg BUILD_DATE="${BUILD_DATE}" \ 90 | --build-arg BUILD_VERSION="${BUILD_VERSION}" \ 91 | --build-arg ICINGA2_VERSION="${ICINGA2_VERSION}" \ 92 | --build-arg CERT_SERVICE_TYPE="${CERT_SERVICE_TYPE}" \ 93 | --build-arg CERT_SERVICE_VERSION="${CERT_SERVICE_VERSION}" \ 94 | --tag "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-${ICINGA2_TYPE}" . 95 | else 96 | 97 | docker build \ 98 | --file "Dockerfile.${ICINGA2_TYPE}" \ 99 | --compress \ 100 | --cache-from "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base" \ 101 | --build-arg BUILD_IMAGE="${BUILD_IMAGE}" \ 102 | --build-arg VCS_REF="${GIT_SHA1}" \ 103 | --build-arg BUILD_DATE="${BUILD_DATE}" \ 104 | --build-arg BUILD_VERSION="${BUILD_VERSION}" \ 105 | --build-arg ICINGA2_VERSION="${ICINGA2_VERSION}" \ 106 | --tag "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-${ICINGA2_TYPE}" . 107 | fi 108 | 109 | echo "" 110 | docker images "${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-${ICINGA2_TYPE}" | tail -n1 111 | echo "" 112 | echo "---------------------------------------------------------------------" 113 | fi 114 | 115 | echo "" 116 | -------------------------------------------------------------------------------- /hooks/clean: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | images=$(docker images -q -f dangling=true) 9 | 10 | [[ -n "${images}" ]] && docker rmi --force ${images} 11 | 12 | images=$(docker images -q *${DOCKER_IMAGE_NAME}* | uniq) 13 | 14 | if [[ ! -z "${images}" ]] 15 | then 16 | docker rmi \ 17 | --force ${images} 18 | fi 19 | 20 | pushd build > /dev/null 21 | 22 | [[ -d ruby-icinga-cert-service ]] && rm -rf ruby-icinga-cert-service 23 | 24 | popd 25 | -------------------------------------------------------------------------------- /hooks/compose-file: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | cat << EOF > .env 9 | BUILD_IMAGE=${BUILD_IMAGE} 10 | BUILD_DATE=${BUILD_DATE} 11 | BUILD_VERSION=${BUILD_VERSION} 12 | ICINGA2_VERSION=$(./hooks/latest-version.sh) 13 | 14 | CERT_SERVICE_TYPE=${CERT_SERVICE_TYPE} 15 | CERT_SERVICE_VERSION=${CERT_SERVICE_VERSION} 16 | 17 | # prints some debug information of the configurations scripts 18 | # 0 = off, 1 = on 19 | DEBUG=0 20 | 21 | # stop the configuration scripts 22 | # 0 = off, 1 = on 23 | DEVELOPMENT_MODUS=0 24 | 25 | # for the icinga-cert-service 26 | # info, notice, warning, debug 27 | LOG_LEVEL=notice 28 | 29 | # notice, debug, warning, critical 30 | ICINGA2_LOGLEVEL=critical 31 | 32 | ICINGA2_MASTER=icinga2-master.matrix.lan 33 | ICINGA2_PARENT=icinga2-master.matrix.lan 34 | 35 | DEMO_DATA=false 36 | 37 | # graphite support 38 | # CARBON_HOST=graphite.matrix.lan 39 | # CARBON_PORT=2003 40 | 41 | # influx 42 | INFLUXDB_DB=icinga2 43 | INFLUXDB_HTTP_AUTH_ENABLED=true 44 | INFLUXDB_ADMIN_USER=admin 45 | INFLUXDB_ADMIN_PASSWORD=hqkBGSQW34iDRpbU 46 | INFLUXDB_USER=icinga2 47 | INFLUXDB_USER_PASSWORD=w7uK6nfcxR6ZBtZC 48 | 49 | # influx integration 50 | INFLUXDB_HOST=influx.matrix.lan 51 | INFLUXDB_PASS=w7uK6nfcxR6ZBtZC 52 | 53 | 54 | # grafana 55 | URL_PATH=/grafana 56 | # LOG_LEVEL=info 57 | ROUTER_LOGGING=false 58 | 59 | GRAFANA_HOST=grafana 60 | GRAFANA_PORT=3000 61 | GRAFANA_AUTHENTICATION=token 62 | GRAFANA_TOKEN= 63 | GRAFANA_ENABLE_LINK=yes 64 | GRAFANA_SHOW_DEBUG=0 65 | GRAFANA_PUBLIC=yes 66 | GRAFANA_PUBLIC_HOST=localhost/grafana 67 | GRAFANA_PUBLIC_PROTOCOL=https 68 | GRAFANA_THEME=light 69 | 70 | GRAFANA_DASHBOARD_UID=icinga2-default 71 | 72 | GRAFANA_PUBLIC_HTTP_PATH=/grafana 73 | 74 | 75 | # mariadb 76 | MARIADB_SYSTEM_USER=root 77 | MARIADB_ROOT_PASSWORD=vYUQ14SGVrJRi69PsujC 78 | MYSQL_ROOT_PASS=vYUQ14SGVrJRi69PsujC 79 | IDO_PASSWORD=qUVuLTk9oEDUV0A 80 | 81 | BASIC_AUTH_PASS=admin 82 | BASIC_AUTH_USER=admin 83 | 84 | CERT_SERVICE_BA_USER=admin 85 | CERT_SERVICE_BA_PASSWORD=admin 86 | CERT_SERVICE_API_USER=root 87 | CERT_SERVICE_API_PASSWORD=icinga 88 | CERT_SERVICE_SERVER=nginx.matrix.lan 89 | CERT_SERVICE_PORT=443 90 | CERT_SERVICE_PATH=/cert-service/ 91 | 92 | TICKET_SALT=4QFITXxpOJXtQwuQXhD6oclZ3UPGVGT20s4s28uV 93 | 94 | EOF 95 | 96 | docker-compose \ 97 | --file compose/head.yml \ 98 | --file compose/database.yml \ 99 | --file compose/nginx.yml \ 100 | --file compose/master.yml \ 101 | --file compose/satellite.yml \ 102 | config > docker-compose.yml 103 | 104 | # --file compose/icingaweb2.yml \ 105 | # --file compose/influxdb.yml \ 106 | # --file compose/grafana.yml \ 107 | -------------------------------------------------------------------------------- /hooks/environment: -------------------------------------------------------------------------------- 1 | 2 | DATA_DIR="${PWD}/data" 3 | 4 | PORTS=" 5 | --publish 80:80 \ 6 | --publish 443:443" 7 | 8 | VOLUMES="" 9 | 10 | ENV="" 11 | 12 | -------------------------------------------------------------------------------- /hooks/exec: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | # Custom build for Docker Hub 6 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 7 | 8 | [[ -e hooks/environment ]] && . hooks/environment 9 | 10 | docker exec \ 11 | --interactive \ 12 | --tty \ 13 | ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 14 | /bin/bash 15 | -------------------------------------------------------------------------------- /hooks/latest-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | data=$(curl \ 4 | --silent \ 5 | --location \ 6 | https://packages.icinga.com/debian/dists/icinga-jessie/main/binary-amd64/Packages) 7 | 8 | echo -e "${data}" | \ 9 | grep -E "^Package: icinga2-bin" -A 7 | \ 10 | grep "Version: " | \ 11 | sort --version-sort | \ 12 | tail -n 1 | \ 13 | sed -e 's|Version: ||' -e 's|-1.jessie||' 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /hooks/publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | if [ -z "${ICINGA2_TYPE}" ] 6 | then 7 | docker tag \ 8 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base \ 9 | bodsch/docker-icinga2:latest-base 10 | 11 | docker push bodsch/docker-icinga2:latest-base 12 | 13 | if [ ! -z "${ICINGA2_VERSION}" ] 14 | then 15 | docker tag \ 16 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-base \ 17 | bodsch/docker-icinga2:${ICINGA2_VERSION}-base 18 | 19 | docker push bodsch/docker-icinga2:${ICINGA2_VERSION}-base 20 | fi 21 | 22 | 23 | #else 24 | # 25 | # if [ "${ICINGA2_TYPE}" = "master" ] 26 | # then 27 | # 28 | # else 29 | # 30 | # 31 | # fi 32 | 33 | fi 34 | -------------------------------------------------------------------------------- /hooks/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 11 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | --privileged \ 13 | ${PORTS} \ 14 | ${VOLUMES} \ 15 | ${ENV} \ 16 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} 17 | -------------------------------------------------------------------------------- /hooks/shell: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 11 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | --interactive \ 13 | --tty \ 14 | --cap-add=SYS_ADMIN \ 15 | --entrypoint '' \ 16 | ${PORTS} \ 17 | ${VOLUMES} \ 18 | ${ENV} \ 19 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION}-${1} \ 20 | /bin/bash 21 | -------------------------------------------------------------------------------- /hooks/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --detach \ 11 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 13 | --privileged \ 14 | ${PORTS} \ 15 | ${VOLUMES} \ 16 | ${ENV} \ 17 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} 18 | -------------------------------------------------------------------------------- /hooks/stop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | # Custom build for Docker Hub 6 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 7 | 8 | [[ -e hooks/environment ]] && . hooks/environment 9 | 10 | docker stop \ 11 | ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} 12 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/api-users.conf: -------------------------------------------------------------------------------- 1 | 2 | object ApiUser "root" { 3 | password = "icinga" 4 | client_cn = NodeName 5 | permissions = [ "*" ] 6 | } 7 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/functions.conf: -------------------------------------------------------------------------------- 1 | 2 | globals.check_dictionary = function(config, key) { 3 | log(config) 4 | log(key) 5 | if (typeof(config) != Dictionary) { 6 | log("config != Dictionary") 7 | log( typeof(config).to_string() ) 8 | return false 9 | } 10 | for( k => v in config) { 11 | if(k == key) { 12 | return v 13 | } 14 | } 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/groups.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * Host group examples. 3 | */ 4 | /* 5 | object HostGroup "linux-servers" { 6 | display_name = "Linux Servers" 7 | assign where host.vars.os == "Linux" 8 | } 9 | 10 | object HostGroup "windows-servers" { 11 | display_name = "Windows Servers" 12 | assign where host.vars.os == "Windows" 13 | } 14 | */ 15 | 16 | object HostGroup "icinga-satellites" { 17 | display_name = "Icinga2 Satellites" 18 | assign where host.vars.satellite 19 | } 20 | 21 | 22 | /* 23 | * Service group examples. 24 | */ 25 | 26 | object ServiceGroup "ping" { 27 | display_name = "Ping Checks" 28 | assign where match("ping*", service.name) 29 | } 30 | 31 | object ServiceGroup "http" { 32 | display_name = "HTTP Checks" 33 | assign where match("http*", service.check_command) 34 | } 35 | 36 | /* 37 | object ServiceGroup "disk" { 38 | display_name = "Disk Checks" 39 | assign where match("disk*", service.check_command) 40 | } 41 | */ 42 | 43 | object ServiceGroup "icinga" { 44 | display_name = "Icinga Checks" 45 | assign where match("icinga*", service.name) 46 | } 47 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/hosts.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * Host definitions with object attributes 3 | * used for apply rules for Service, Notification, 4 | * Dependency and ScheduledDowntime objects. 5 | * 6 | * Tip: Use `icinga2 object list --type Host` to 7 | * list all host objects after running 8 | * configuration validation (`icinga2 daemon -C`). 9 | */ 10 | 11 | object Host NodeName { 12 | import "generic-host" 13 | address = "127.0.0.1" 14 | vars.os = "Docker" 15 | } 16 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/satellite_hostgroup.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * Create a Hostgroup for all Icinga Satellites 3 | */ 4 | 5 | /* 6 | object HostGroup "icinga-satellites" { 7 | display_name = "Icinga2 Satellites" 8 | assign where host.vars.satellite 9 | } 10 | */ 11 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/conf.d/services.conf.docker: -------------------------------------------------------------------------------- 1 | /* 2 | * Service apply rules. 3 | * 4 | * especially for a docker environment 5 | * 6 | * 7 | * Tip: Use `icinga2 object list --type Service` to 8 | * list all service objects after running 9 | * configuration validation (`icinga2 daemon -C`). 10 | */ 11 | 12 | /* 13 | * These are generic `ping4` and `ping6` 14 | * checks applied to all hosts having the 15 | * `address` resp. `address6` attribute 16 | * defined. 17 | */ 18 | apply Service "ping4" { 19 | import "generic-service" 20 | check_command = "ping4" 21 | 22 | assign where host.address 23 | ignore where host.vars.alive_dummy 24 | } 25 | 26 | /* 27 | apply Service for (disk => config in host.vars.disks) { 28 | import "generic-service" 29 | 30 | check_command = "disk" 31 | 32 | vars += config 33 | assign where host.name == NodeName 34 | } 35 | */ 36 | 37 | apply Service "icinga" { 38 | import "generic-service" 39 | 40 | check_command = "icinga" 41 | assign where host.name == NodeName 42 | } 43 | 44 | /* 45 | apply Service "load" { 46 | import "generic-service" 47 | 48 | check_command = "load" 49 | assign where host.name == NodeName 50 | } 51 | */ 52 | 53 | 54 | /* 55 | * Apply the `ssh` service to all hosts 56 | * with the `address` attribute defined and 57 | * the custom attribute `os` set to `Linux`. 58 | */ 59 | /* 60 | apply Service "ssh" { 61 | import "generic-service" 62 | 63 | check_command = "ssh" 64 | assign where (host.address || host.address6) && host.vars.os == "Linux" 65 | } 66 | 67 | apply Service for (http_vhost => config in host.vars.http_vhosts) { 68 | import "generic-service" 69 | 70 | check_command = "http" 71 | 72 | vars += config 73 | } 74 | 75 | apply Service "procs" { 76 | import "generic-service" 77 | 78 | check_command = "procs" 79 | assign where host.name == NodeName && host.vars.os == "Linux" 80 | } 81 | 82 | apply Service "swap" { 83 | import "generic-service" 84 | 85 | check_command = "swap" 86 | assign where host.name == NodeName && host.vars.os == "Linux" 87 | } 88 | 89 | apply Service "users" { 90 | import "generic-service" 91 | 92 | check_command = "users" 93 | assign where host.name == NodeName && host.vars.os == "Linux" 94 | } 95 | */ 96 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/constants.conf-SAVE: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/features-available/livestatus.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * THIS FILE IS OBSOLETE AND WILL BE REMOVED IN NEAR FUTURE 3 | * 4 | * https://www.axxeo.de/blog/technisches/icinga2-livestatus-ueber-tcp.html 5 | */ 6 | 7 | library "livestatus" 8 | 9 | object LivestatusListener "livestatus" { } 10 | 11 | object LivestatusListener "livestatus-tcp" { 12 | socket_type = "tcp" 13 | bind_host = "0.0.0.0" 14 | bind_port = "6666" 15 | } 16 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/icinga2.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | include "constants.conf" 6 | // include_recursive "satellites.d" 7 | include "zones.conf" 8 | include 9 | include 10 | include 11 | include "features-enabled/*.conf" 12 | include_recursive "conf.d" 13 | // include_recursive "demo" 14 | 15 | // EOF 16 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/master.d/checkcommands_linux_memory.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | * 5 | */ 6 | 7 | object CheckCommand "check_memory" { 8 | import "plugin-check-command" 9 | 10 | command = [ PluginDir + "/check_mem" ] 11 | 12 | arguments = { 13 | "-w" = { 14 | description = "Your warning %. 20 means 20% of your memory can remain before a warning alarm. Do not use the % sign." 15 | value = "$mem_warning$" 16 | set_if = bool("$mem_warning$") 17 | } 18 | "-c" = { 19 | description = "Your critical %. 10 means 10% of your memory can remain before a critical alarm. Do not use the % sign." 20 | value = "$mem_critical$" 21 | set_if = bool("$mem_critical$") 22 | } 23 | "-d" = { 24 | description = "divider K=kilobytes, M=megabytes, G=gigabytes, T=terabytes" 25 | value = "M" 26 | } 27 | "-f" = { 28 | description = "Include cached memory as free memory when calculating your percentage free" 29 | value = "$mem_cached_memory$" 30 | set_if = bool("$mem_cached_memory$") 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/master.d/satellite_services.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * YOU SHOULD KNOW WHAT YOU'RE DOING! 3 | * 4 | * THIS CONFIGURATION FILE MUST BE SYNCRON WITH 'satellite.d/services.conf' BE! 5 | * 6 | * EXCEPTIONS ARE command_endpoint AND assign RULES 7 | */ 8 | 9 | apply Service "icinga-satellite" { 10 | import "icinga-satellite-service" 11 | check_command = "icinga" 12 | 13 | max_check_attempts = 2 14 | check_interval = 30s 15 | retry_interval = 10s 16 | enable_notifications = true 17 | 18 | command_endpoint = host.vars.remote_endpoint 19 | assign where host.vars.satellite 20 | } 21 | 22 | apply Service "load" { 23 | import "icinga-satellite-service" 24 | check_command = "load" 25 | 26 | check_interval = 45s 27 | retry_interval = 10s 28 | 29 | command_endpoint = host.vars.remote_endpoint 30 | assign where host.vars.satellite 31 | } 32 | 33 | apply Service for (disk => config in host.vars.disks) { 34 | import "icinga-satellite-service" 35 | check_command = "disk" 36 | 37 | check_interval = 45s 38 | retry_interval = 10s 39 | 40 | vars += config 41 | 42 | command_endpoint = host.vars.remote_endpoint 43 | assign where host.vars.satellite 44 | } 45 | 46 | apply Service "memory" { 47 | import "icinga-satellite-service" 48 | check_command = "check_memory" 49 | 50 | check_interval = 45s 51 | retry_interval = 10s 52 | 53 | command_endpoint = host.vars.remote_endpoint 54 | assign where host.vars.satellite && host.vars.memory 55 | ignore where host.vars.os == "Windows" 56 | } 57 | 58 | /** 59 | * generic HTTP check for all vhosts in vars.http_vhost 60 | */ 61 | apply Service "http_" for (http_vhost => config in host.vars.http_vhosts) { 62 | import "generic-service" 63 | check_command = "http" 64 | 65 | display_name = "HTTP Page" 66 | notes = "check against a HTTP Page" 67 | 68 | vars += config 69 | 70 | max_check_attempts = 3 71 | check_interval = 45s 72 | retry_interval = 20s 73 | enable_notifications = true 74 | 75 | assign where host.vars.http_vhosts 76 | } 77 | 78 | /** 79 | * generic HTTPS check for all vhosts in vars.https_vhost 80 | */ 81 | apply Service "https_" for (https_vhost => config in host.vars.https_vhosts) { 82 | import "generic-service" 83 | check_command = "http" 84 | 85 | display_name = "HTTPS Page" 86 | notes = "check against a HTTPS Page" 87 | 88 | 89 | vars = { 90 | "http_uri" = https_vhost 91 | "http_sni" = true 92 | "http_ssl" = true 93 | "http_vhost" = host.name 94 | "http_address" = host.address 95 | } 96 | 97 | max_check_attempts = 5 98 | check_interval = 3m 99 | retry_interval = 2 100 | enable_notifications = true 101 | 102 | assign where host.vars.https_vhosts 103 | } 104 | 105 | apply Service "ssllabs_grade" { 106 | import "icinga-satellite-service" 107 | check_command = "check_ssl_cert" 108 | 109 | display_name = "SSL Labs Grade" 110 | notes_url = "https://www.ssllabs.com/ssltest/analyze.html?d=" + host.name 111 | 112 | vars = { 113 | "ssl_address" = host.name 114 | "ssl-labs-grade" = host.vars.ssl_grade 115 | } 116 | 117 | max_check_attempts = 5 118 | check_interval = 2h 119 | retry_interval = 2 120 | enable_notifications = true 121 | 122 | assign where host.vars.ssl_grade 123 | } 124 | 125 | /** 126 | * file_age check 127 | * 128 | * curl -k -s -u root:icinga --header 'Accept: application/json' --request PUT \ 129 | * 'https://localhost:5665/v1/objects/hosts/www.foo.bar' 130 | * --data ' 131 | * { 132 | * "templates": [ "dummy-server" ], "attrs": { "address": "www.foo.bar", "check_command": "dummy", 133 | * "vars": { "file_age": { "/tmp/foo": { "warning_time": 76800, "critical_time": 128000 } } } } 134 | * }' 135 | * 136 | **/ 137 | apply Service "file_" for ( file => config in host.vars.file_age) { 138 | import "icinga-satellite-service" 139 | check_command = "file_age" 140 | 141 | display_name = "File Age for " + file 142 | notes = "check a file age" 143 | 144 | vars = { 145 | "file_age_file" = file 146 | } 147 | 148 | var warn_time = check_dictionary( config, "warning_time" ) 149 | var crit_time = check_dictionary( config, "critical_time" ) 150 | var warn_size = check_dictionary( config, "warning_size" ) 151 | var crit_size = check_dictionary( config, "critical_size" ) 152 | 153 | if( warn_time && crit_time ) { 154 | vars += { 155 | "file_age_warning_time" = config.warning_time 156 | "file_age_critical_time" = config.critical_time 157 | } 158 | } 159 | 160 | if( warn_size && crit_size ) { 161 | vars += { 162 | "file_age_warning_size" = config.warning_size 163 | "file_age_critical_size" = config.critical_size 164 | } 165 | } 166 | 167 | /* "file_age_ignoremissing" = config.ignoremissing*/ 168 | 169 | max_check_attempts = 5 170 | check_interval = 10m 171 | retry_interval = 2 172 | enable_notifications = true 173 | 174 | assign where host.vars.file_age 175 | } 176 | 177 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/master.d/templates_services.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | */ 4 | 5 | template Host "satellite-host" { 6 | check_command = "hostname" 7 | } 8 | 9 | template Service "icinga-satellite-service" { 10 | import "generic-service" 11 | command_endpoint = host.vars.remote_endpoint 12 | zone = host.vars.remote_endpoint 13 | } 14 | 15 | template Host "default-host-ping" { 16 | check_command = "ping4" 17 | max_check_attempts = 5 18 | check_interval = 3m 19 | retry_interval = 2m 20 | 21 | /* 22 | check_period = host.vars.check_period "24x7" 23 | enable_notifications = true 24 | vars.fping_wrta = 1000 25 | vars.fping_wpl = 100 26 | vars.fping_crta = 2000 27 | vars.fping_cpl = 100 28 | vars.fping_number = 2 29 | vars.fping_interval = 500 30 | */ 31 | } 32 | 33 | template Host "dummy-server" { 34 | check_command = "dummy" 35 | } 36 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/satellite.d/commands.conf: -------------------------------------------------------------------------------- 1 | 2 | object CheckCommand "hostname" { 3 | 4 | import "plugin-check-command" 5 | 6 | command = [ "/usr/lib/monitoring-plugins/check_hostname" ] 7 | } 8 | 9 | /* 10 | * 11 | * 12 | * 13 | */ 14 | object CheckCommand "check_memory" { 15 | import "plugin-check-command" 16 | 17 | command = [ PluginDir + "/check_mem" ] 18 | 19 | arguments = { 20 | "-w" = { 21 | description = "Sets warning value for Memory Usage. Default is 95%" 22 | value = "$mem_warning$" 23 | set_if = bool("$mem_warning$") 24 | } 25 | "-c" = { 26 | description = "Sets critical value for Memory Usage. Default is 98%" 27 | value = "$mem_critical$" 28 | set_if = bool("$mem_critical$") 29 | } 30 | "-W" = { 31 | description = "Sets warning value for Swap Usage. Default is 95%" 32 | value = "$swap_warning$" 33 | set_if = bool("$swap_warning$") 34 | } 35 | "-C" = { 36 | description = "Sets critical value for Swap Usage. Default is 98%" 37 | value = "$swap_critical$" 38 | set_if = bool("$swap_critical$") 39 | } 40 | } 41 | } 42 | 43 | object CheckCommand "check_ssl_cert" { 44 | import "plugin-check-command" 45 | 46 | command = [ PluginDir + "/check_ssl_cert" ] 47 | 48 | arguments = { 49 | "--host" = { 50 | value = "$ssl_address$" 51 | description = "Host address" 52 | } 53 | "--port" = { 54 | value = "$ssl_port$" 55 | description ="TCP port (default: 443)" 56 | } 57 | "--check-ssl-labs" = { 58 | description = "SSL Labs assessment" 59 | value = "$ssl-labs-grade$" 60 | set_if = bool("$ssl-labs-grade$") 61 | } 62 | } 63 | 64 | vars.ssl_cert_valid_days_warn = false 65 | vars.ssl_cert_valid_days_critical = false 66 | } 67 | 68 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/satellite.d/services.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * YOU SHOULD KNOW WHAT YOU'RE DOING! 3 | * 4 | * THIS CONFIGURATION FILE MUST BE SYNCRON WITH 'master.d/satellite_services.conf' BE! 5 | * 6 | * EXCEPTIONS ARE command_endpoint AND assign RULES 7 | */ 8 | 9 | apply Service "icinga-satellite" { 10 | import "icinga-satellite-service" 11 | check_command = "icinga" 12 | 13 | max_check_attempts = 2 14 | check_interval = 30s 15 | retry_interval = 10s 16 | enable_notifications = true 17 | 18 | assign where host.name == NodeName 19 | } 20 | 21 | apply Service "load" { 22 | import "icinga-satellite-service" 23 | check_command = "load" 24 | 25 | check_interval = 45s 26 | retry_interval = 10s 27 | 28 | assign where host.name == NodeName 29 | } 30 | 31 | apply Service for (disk => config in host.vars.disks) { 32 | import "icinga-satellite-service" 33 | check_command = "disk" 34 | 35 | check_interval = 45s 36 | retry_interval = 10s 37 | 38 | vars += config 39 | 40 | assign where host.name == NodeName 41 | } 42 | 43 | apply Service "memory" { 44 | import "icinga-satellite-service" 45 | check_command = "check_memory" 46 | 47 | check_interval = 45s 48 | retry_interval = 10s 49 | 50 | assign where host.name == NodeName 51 | } 52 | 53 | apply Service "http_" for (http_vhost => config in host.vars.http_vhosts) { 54 | import "icinga-satellite-service" 55 | check_command = "http" 56 | 57 | display_name = "HTTP Page" 58 | notes = "check against a HTTP Page" 59 | 60 | vars += config 61 | 62 | max_check_attempts = 3 63 | check_interval = 45s 64 | retry_interval = 20s 65 | enable_notifications = true 66 | 67 | assign where host.name == NodeName 68 | } 69 | 70 | /** 71 | * generic HTTPS check for all vhosts in vars.https_vhost 72 | */ 73 | apply Service "https_" for (https_vhost => config in host.vars.https_vhosts) { 74 | import "icinga-satellite-service" 75 | check_command = "http" 76 | 77 | display_name = "HTTPS Page" 78 | notes = "check against a HTTPS Page" 79 | 80 | 81 | vars = { 82 | "http_uri" = https_vhost 83 | "http_sni" = true 84 | "http_ssl" = true 85 | "http_vhost" = host.name 86 | "http_address" = host.address 87 | } 88 | 89 | max_check_attempts = 5 90 | check_interval = 3m 91 | retry_interval = 2 92 | enable_notifications = true 93 | 94 | assign where host.name == NodeName 95 | } 96 | 97 | apply Service "ssllabs_grade" { 98 | import "icinga-satellite-service" 99 | check_command = "check_ssl_cert" 100 | 101 | display_name = "SSL Labs Grade" 102 | notes_url = "https://www.ssllabs.com/ssltest/analyze.html?d=" + host.name 103 | 104 | vars = { 105 | "ssl_address" = host.name 106 | "ssl-labs-grade" = host.vars.ssl_grade 107 | } 108 | 109 | max_check_attempts = 5 110 | check_interval = 2h 111 | retry_interval = 2 112 | enable_notifications = true 113 | 114 | assign where host.name == NodeName && host.vars.ssl_grade 115 | } 116 | 117 | apply Service "file_" for ( file => config in host.vars.file_age) { 118 | import "icinga-satellite-service" 119 | check_command = "file_age" 120 | 121 | display_name = "File Age for " + file 122 | notes = "check a file age" 123 | 124 | vars = { 125 | "file_age_file" = file 126 | } 127 | 128 | var warn_time = check_dictionary( config, "warning_time" ) 129 | var crit_time = check_dictionary( config, "critical_time" ) 130 | var warn_size = check_dictionary( config, "warning_size" ) 131 | var crit_size = check_dictionary( config, "critical_size" ) 132 | 133 | if( warn_time && crit_time ) { 134 | vars += { 135 | "file_age_warning_time" = config.warning_time 136 | "file_age_critical_time" = config.critical_time 137 | } 138 | } 139 | 140 | if( warn_size && crit_size ) { 141 | vars += { 142 | "file_age_warning_size" = config.warning_size 143 | "file_age_critical_size" = config.critical_size 144 | } 145 | } 146 | 147 | /* "file_age_ignoremissing" = config.ignoremissing*/ 148 | 149 | max_check_attempts = 5 150 | check_interval = 10m 151 | retry_interval = 2 152 | enable_notifications = true 153 | 154 | assign where host.name == NodeName 155 | } 156 | 157 | -------------------------------------------------------------------------------- /rootfs/etc/icinga2/zones.conf-docker: -------------------------------------------------------------------------------- 1 | /* 2 | * initial zones.conf 3 | * The requires `NodeName` are defined in constants.conf. 4 | */ 5 | 6 | object Zone "global-templates" { global = true } 7 | object Zone "director-global" { global = true } 8 | 9 | object Endpoint NodeName { host = NodeName } 10 | object Zone ZoneName { endpoints = [ NodeName ] } 11 | -------------------------------------------------------------------------------- /rootfs/etc/s6/.s6-svscan/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodsch/docker-icinga2/f5110537d8abf7fb155f1d1b7e7d66f2cc6e38cf/rootfs/etc/s6/.s6-svscan/.keep -------------------------------------------------------------------------------- /rootfs/etc/s6/icinga2-cert-service/run: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | PROGARGS="" 4 | PROGHOME="/" 5 | PROGNAME="/usr/local/bin/rest-service.rb" 6 | 7 | exec ${PROGNAME} ${PROGARGS} 8 | -------------------------------------------------------------------------------- /rootfs/etc/s6/icinga2/run: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | PROGARGS="daemon -c /etc/icinga2/icinga2.conf -e /var/log/icinga2/error.log" 4 | PROGHOME="/usr/lib/icinga2" 5 | PROGNAME="/usr/sbin/icinga2" 6 | 7 | ## HACK - s6 doesn't handle forking well (at all?) 8 | ## Kill the service after a reload to allow s6 to take over. 9 | /bin/sleep 1 10 | /usr/bin/killall icinga2 2> /dev/null 11 | ## 12 | 13 | exec ${PROGNAME} ${PROGARGS} 14 | -------------------------------------------------------------------------------- /rootfs/init/api_user.sh: -------------------------------------------------------------------------------- 1 | 2 | # create API users 3 | # 4 | create_api_user() { 5 | 6 | local api_file="/etc/icinga2/conf.d/api-users.conf" 7 | local api_users= 8 | 9 | # the format are following: 10 | # username:password,username:password, ... 11 | # for example: 12 | # ICINGA2_API_USERS=root:icinga,dashing:dashing,cert:foo-bar 13 | # 14 | [[ -n "${ICINGA2_API_USERS}" ]] && api_users=$(echo ${ICINGA2_API_USERS} | sed -e 's/,/ /g' -e 's/\s+/\n/g' | uniq) 15 | 16 | if [[ ! -z "${api_users}" ]] 17 | then 18 | 19 | if [[ $(cat ${api_file} | wc -l) -eq 6 ]] 20 | then 21 | log_info "create configuration for API users ..." 22 | 23 | # the initial configuration 24 | # make it blank and create our default users 25 | # 26 | echo "" > ${api_file} 27 | 28 | for u in ${api_users} 29 | do 30 | user=$(echo "${u}" | cut -d: -f1) 31 | pass=$(echo "${u}" | cut -d: -f2) 32 | 33 | [[ -z ${pass} ]] && pass=${user} 34 | 35 | if [[ $(grep -c "object ApiUser \"${user}\"" ${api_file}) -eq 0 ]] 36 | then 37 | log_info " add user '${user}'" 38 | 39 | cat << EOF >> ${api_file} 40 | 41 | object ApiUser "${user}" { 42 | password = "${pass}" 43 | client_cn = NodeName 44 | permissions = [ "*" ] 45 | } 46 | 47 | EOF 48 | fi 49 | done 50 | fi 51 | fi 52 | 53 | } 54 | 55 | create_api_user 56 | -------------------------------------------------------------------------------- /rootfs/init/cert/certificate_handler.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | # create a local CA for the icinga2 master 4 | # 5 | create_ca() { 6 | 7 | # create the CA, when they not exist 8 | # 9 | if [[ ! -f ${ICINGA2_LIB_DIRECTORY}/ca/ca.crt ]] 10 | then 11 | log_info "create new CA for '${HOSTNAME}'" 12 | 13 | # ls -ltha /var/lib/icinga2 14 | 15 | [[ -f ${PKI_KEY_FILE} ]] && rm -rf ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}* 16 | 17 | /usr/sbin/icinga2 \ 18 | api \ 19 | setup \ 20 | --log-level ${ICINGA2_LOGLEVEL} 21 | 22 | # api setup has failed 23 | # we remove all cert related directies and files and leave the container 24 | # after an restart, we start from scratch 25 | # 26 | if [[ $? -gt 0 ]] 27 | then 28 | log_error "API Setup has failed" 29 | rm -rf ${ICINGA2_LIB_DIRECTORY}/ca 2> /dev/null 30 | rm -rf ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}* 2> /dev/null 31 | 32 | exit 1 33 | fi 34 | fi 35 | 36 | sed -i \ 37 | -e "s|^.*\ NodeName\ \=\ .*|const\ NodeName\ \=\ \"${HOSTNAME}\"|g" \ 38 | -e "s|^.*\ ZoneName\ \=\ .*|const\ ZoneName\ \=\ \"${HOSTNAME}\"|g" \ 39 | /etc/icinga2/constants.conf 40 | 41 | # icinga2 API cert - regenerate new private key and certificate when running in a new container 42 | # 43 | if [[ ! -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] 44 | then 45 | log_info "create new certificate" 46 | 47 | /usr/sbin/icinga2 \ 48 | pki \ 49 | new-cert \ 50 | --cn ${HOSTNAME} \ 51 | --key ${PKI_KEY_FILE} \ 52 | --csr ${PKI_CSR_FILE} \ 53 | --log-level ${ICINGA2_LOGLEVEL} 54 | 55 | /usr/sbin/icinga2 \ 56 | pki \ 57 | sign-csr \ 58 | --csr ${PKI_CSR_FILE} \ 59 | --cert ${PKI_CRT_FILE} \ 60 | --log-level ${ICINGA2_LOGLEVEL} 61 | 62 | correct_rights 63 | 64 | validate_icinga_config 65 | 66 | chown -R ${USER}:${GROUP} ${ICINGA2_CERT_DIRECTORY} 67 | chmod 600 ${ICINGA2_CERT_DIRECTORY}/*.key 68 | chmod 644 ${ICINGA2_CERT_DIRECTORY}/*.crt 69 | 70 | log_info "Finished cert generation" 71 | fi 72 | } 73 | 74 | 75 | # validate our lokal certificate against our certificate service 76 | # with an API Request against 77 | # http://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/validate/${checksum}) 78 | # 79 | # if this failed, the PKI schould be removed 80 | # 81 | validate_local_ca() { 82 | 83 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/ca.crt ]] 84 | then 85 | log_info "validate our CA file against our master" 86 | 87 | . /init/wait_for/cert_service.sh 88 | 89 | checksum=$(sha256sum ${ICINGA2_CERT_DIRECTORY}/ca.crt | cut -f 1 -d ' ') 90 | 91 | # validate our ca file 92 | # 93 | code=$(curl \ 94 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 95 | --silent \ 96 | --location \ 97 | --insecure \ 98 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 99 | --header "X-API-KEY: ${CERT_SERVICE_API_PASSWORD}" \ 100 | --write-out "%{http_code}\n" \ 101 | --output /tmp/validate_ca_${HOSTNAME}.json \ 102 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}/v2/validate/${checksum}) 103 | 104 | result=${?} 105 | 106 | if [[ "${DEBUG}" = "true" ]] 107 | then 108 | log_debug "result: '${result}' - status: '${code}'" 109 | 110 | cat /tmp/validate_ca_${HOSTNAME}.json 111 | fi 112 | 113 | if [[ ${result} -eq 0 ]] && [[ ${code} = 200 ]] 114 | then 115 | rm -f /tmp/validate_ca_${HOSTNAME}.json 116 | 117 | elif [[ ${result} -eq 0 ]] && [[ ${code} = 502 ]] 118 | then 119 | log_warn "our webservice has an problem" 120 | sleep 10s 121 | validate_local_ca 122 | else 123 | 124 | cat /tmp/validate_ca_${HOSTNAME}.json 125 | 126 | status=$(echo "${code}" | jq --raw-output .status 2> /dev/null) 127 | msg=$(echo "${code}" | jq --raw-output .message 2> /dev/null) 128 | 129 | log_warn "our master has a new CA" 130 | log_warn "${msg}" 131 | 132 | rm -f /tmp/validate_ca_${HOSTNAME}.json 133 | rm -rf ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}* 134 | rm -rf ${ICINGA2_LIB_DIRECTORY}/ca/* 135 | 136 | cat /dev/null > /etc/icinga2/features-available/api.conf 137 | fi 138 | else 139 | # we have no local cert file .. 140 | log_warn "no CA file found" 141 | : 142 | fi 143 | } 144 | 145 | 146 | create_certificate_pem() { 147 | 148 | if [[ -d ${ICINGA2_CERT_DIRECTORY} ]] && [[ ! -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem ]] 149 | then 150 | cd ${ICINGA2_CERT_DIRECTORY} 151 | 152 | if [[ -f ${HOSTNAME}.crt ]] && [[ -f ${HOSTNAME}.key ]] 153 | then 154 | cat ${HOSTNAME}.crt ${HOSTNAME}.key >> ${HOSTNAME}.pem 155 | else 156 | log_warn "can't create certificate pem" 157 | fi 158 | fi 159 | } 160 | -------------------------------------------------------------------------------- /rootfs/init/cert/certificate_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /etc/profile 4 | 5 | . /init/output.sh 6 | . /init/environment.sh 7 | 8 | certificate_with_ticket() { 9 | 10 | [[ -d ${ICINGA2_CERT_DIRECTORY} ]] || mkdir -p ${ICINGA2_CERT_DIRECTORY} 11 | 12 | chmod a+w ${ICINGA2_CERT_DIRECTORY} 13 | 14 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] 15 | then 16 | return 17 | fi 18 | 19 | # create an ticket on the master via: 20 | # icinga2 pki ticket --cn ${HOSTNAME} 21 | 22 | [[ "${DEBUG}" = "true" ]] && log_debug "ask for an PKI ticket" 23 | ticket=$(curl \ 24 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 25 | --silent \ 26 | --location \ 27 | --insecure \ 28 | --request GET \ 29 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 30 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 31 | "${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}/v2/ticket/${HOSTNAME}") 32 | 33 | # enable neccessary features 34 | # icinga2 feature enable api compatlog command 35 | 36 | # the following commands are copied out of the icinga2-documentation 37 | [[ "${DEBUG}" = "true" ]] && log_debug "pki new-cert" 38 | icinga2 pki new-cert \ 39 | --log-level ${ICINGA2_LOGLEVEL} \ 40 | --cn ${HOSTNAME} \ 41 | --key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key \ 42 | --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt 43 | 44 | [[ "${DEBUG}" = "true" ]] && log_debug "pki save-cert" 45 | icinga2 pki save-cert \ 46 | --log-level ${ICINGA2_LOGLEVEL} \ 47 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt \ 48 | --host ${ICINGA2_MASTER} 49 | 50 | [[ "${DEBUG}" = "true" ]] && log_debug "pki request" 51 | icinga2 pki request \ 52 | --log-level ${ICINGA2_LOGLEVEL} \ 53 | --host ${ICINGA2_MASTER} \ 54 | --port ${ICINGA2_MASTER_PORT} \ 55 | --ticket ${ticket} \ 56 | --key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key \ 57 | --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt \ 58 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt \ 59 | --ca ${ICINGA2_CERT_DIRECTORY}/ca.crt 60 | 61 | #--endpoint ${ICINGA2_MASTER} \ # ,${ICINGA2_MASTER},${ICINGA2_MASTER_PORT} \ 62 | 63 | [[ "${DEBUG}" = "true" ]] && log_debug "node setup" 64 | icinga2 node setup \ 65 | --log-level ${ICINGA2_LOGLEVEL} \ 66 | --accept-config \ 67 | --accept-commands \ 68 | --disable-confd \ 69 | --cn ${HOSTNAME} \ 70 | --zone ${HOSTNAME} \ 71 | --endpoint ${ICINGA2_MASTER} \ 72 | --parent_host ${ICINGA2_MASTER} \ 73 | --parent_zone master \ 74 | --ticket ${ticket} \ 75 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt 76 | 77 | date="$(date "+%Y-%m-%d %H:%M:%S")" 78 | timestamp="$(date "+%s")" 79 | 80 | cat << EOF > ${ICINGA2_LIB_DIRECTORY}/backup/sign_${HOSTNAME}.json 81 | { 82 | "status": 200, 83 | "message": "PKI for ${HOSTNAME}", 84 | "master_name": "${ICINGA2_MASTER}", 85 | "master_ip": "", 86 | "date": "${date}", 87 | "timestamp": ${timestamp} 88 | } 89 | EOF 90 | } 91 | 92 | 93 | 94 | get_certificate_for_the_satellite() { 95 | 96 | local WORK_DIR=/tmp 97 | 98 | validate_local_ca 99 | 100 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] && [[ ${ICINGA2_CERT_DIRECTORY}/ca.crt ]] 101 | then 102 | return 103 | fi 104 | 105 | # 106 | # if [ -f ${ICINGA_CERT_DIR}/${HOSTNAME}.key ] 107 | # then 108 | # return 109 | # fi 110 | 111 | # if [ ${ICINGA_CERT_SERVICE} ] 112 | # then 113 | log_info "we ask our cert-service for a certificate .." 114 | 115 | set -x 116 | code=$(curl \ 117 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 118 | --silent \ 119 | --location \ 120 | --insecure \ 121 | --request GET \ 122 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/icinga-version) 123 | 124 | log_debug "remote icinga version: ${code}" 125 | 126 | # generate a certificate request 127 | # 128 | code=$(curl \ 129 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 130 | --silent \ 131 | --insecure \ 132 | --request GET \ 133 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 134 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 135 | --write-out "%{http_code}\n" \ 136 | --output /tmp/request_${HOSTNAME}.json \ 137 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/request/${HOSTNAME}) 138 | 139 | if ( [ $? -eq 0 ] && [ ${code} -eq 200 ] ) 140 | then 141 | 142 | log_info "certifiacte request was successful" 143 | log_info "download and install the certificate" 144 | 145 | master_name=$(jq --raw-output .master_name /tmp/request_${HOSTNAME}.json) 146 | checksum=$(jq --raw-output .checksum /tmp/request_${HOSTNAME}.json) 147 | 148 | cat /tmp/request_${HOSTNAME}.json 149 | 150 | # rm -f /tmp/request_${HOSTNAME}.json 151 | 152 | mkdir -p ${WORK_DIR}/pki/${HOSTNAME} 153 | 154 | # get our created cert 155 | # 156 | code=$(curl \ 157 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 158 | --silent \ 159 | --insecure \ 160 | --request GET \ 161 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 162 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 163 | --header "X-CHECKSUM: ${checksum}" \ 164 | --write-out "%{http_code}\n" \ 165 | --output ${WORK_DIR}/pki/${HOSTNAME}/${HOSTNAME}.tgz \ 166 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/cert/${HOSTNAME}) 167 | 168 | result="${?}" 169 | 170 | if [[ ${result} -eq 0 ]] && [[ ${code} -eq 200 ]] 171 | then 172 | 173 | cd ${WORK_DIR}/pki/${HOSTNAME} 174 | 175 | # the download has not working 176 | # 177 | if [[ ! -f ${HOSTNAME}.tgz ]] 178 | then 179 | log_error "cert File '${HOSTNAME}.tgz' not found!" 180 | exit 1 181 | fi 182 | 183 | tar -xzf ${HOSTNAME}.tgz 184 | 185 | ls -lth 186 | 187 | if [[ ! -f ${HOSTNAME}.pem ]] 188 | then 189 | cat ${HOSTNAME}.crt ${HOSTNAME}.key >> ${HOSTNAME}.pem 190 | fi 191 | 192 | cp -a ${HOSTNAME}.crt ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt 193 | cp -a ${HOSTNAME}.key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key 194 | cp -a ${HOSTNAME}.pem ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem 195 | cp -a ca.crt ${ICINGA2_CERT_DIRECTORY}/ca.crt 196 | 197 | cp -a /tmp/request_${HOSTNAME}.json /var/lib/icinga2/backup/sign_${HOSTNAME}.json 198 | 199 | # store the master for later restart 200 | # 201 | echo "${master_name}" > ${WORK_DIR}/pki/${HOSTNAME}/master 202 | 203 | create_api_config 204 | 205 | else 206 | log_error "can't download our certificate!" 207 | 208 | rm -rf ${WORK_DIR}/pki 2> /dev/null 209 | 210 | unset ICINGA_API_PKI_PATH 211 | fi 212 | else 213 | 214 | error=$(cat /tmp/request_${HOSTNAME}.json) 215 | 216 | log_error "${code} - the cert-service tell us a problem: '${error}'" 217 | log_error "exit ..." 218 | 219 | rm -f /tmp/request_${HOSTNAME}.json 220 | 221 | exit 1 222 | fi 223 | set +x 224 | 225 | # fi 226 | } 227 | 228 | 229 | 230 | request_certificate_from_master() { 231 | 232 | # we have a certificate 233 | # restore our own zone configuration 234 | # otherwise, we can't communication with the master 235 | # 236 | if ( [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] ) 237 | then 238 | : 239 | else 240 | # no certificate found 241 | # use the node wizard to create a valid certificate request 242 | # 243 | 244 | log_info "use the node wizard to create a valid certificate request" 245 | expect /init/node-wizard.expect 1> /dev/null 246 | 247 | result=${?} 248 | 249 | if [[ "${DEBUG}" = "true" ]] 250 | then 251 | log_debug "the result for the node-wizard was '${result}'" 252 | fi 253 | 254 | # after this, in /var/lib/icinga2/certs/ should be found this files: 255 | # - ca.crt 256 | # - $(hostname -f).key 257 | # - $(hostname -f).crt 258 | # 259 | # these files are absolutly importand for the nexts steps 260 | # we can abort immediately, if it should come to mistakes. 261 | 262 | sleep 8s 263 | 264 | # check transfered certificate files 265 | # 266 | BREAK="false" 267 | for f in ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ${ICINGA2_CERT_DIRECTORY}/ca.crt 268 | do 269 | if [[ -f ${f} ]] 270 | then 271 | : 272 | [[ "${DEBUG}" = "true" ]] && log_debug "file '${f}' exists!" 273 | else 274 | log_error "file '${f}' is missing!" 275 | BREAK="true" 276 | fi 277 | done 278 | 279 | if [[ ${BREAK} = "true" ]] 280 | then 281 | 282 | if [[ ! -f ${ICINGA2_CERT_DIRECTORY}/ca.crt ]] 283 | then 284 | get_ca_file 285 | fi 286 | fi 287 | 288 | # and now we have to ask our master to confirm this certificate 289 | # 290 | log_info "ask our cert-service to sign our certifiacte" 291 | 292 | . /init/wait_for/cert_service.sh 293 | 294 | code=$(curl \ 295 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 296 | --silent \ 297 | --location \ 298 | --insecure \ 299 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 300 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 301 | --write-out "%{http_code}\n" \ 302 | --output /tmp/sign_${HOSTNAME}.json \ 303 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/sign/${HOSTNAME}) 304 | 305 | result=${?} 306 | 307 | if [[ "${DEBUG}" = "true" ]] 308 | then 309 | log_debug "result for sign certificate:" 310 | log_debug "result: '${result}' | code: '${code}'" 311 | log_debug "$(ls -lth /tmp/sign_${HOSTNAME}.json)" 312 | fi 313 | 314 | if [[ ${result} -eq 0 ]] && [[ ${code} == 200 ]] 315 | then 316 | msg=$(jq --raw-output .message /tmp/sign_${HOSTNAME}.json 2> /dev/null) 317 | master_name=$(jq --raw-output .master_name /tmp/sign_${HOSTNAME}.json 2> /dev/null) 318 | master_ip=$(jq --raw-output .master_ip /tmp/sign_${HOSTNAME}.json 2> /dev/null) 319 | 320 | if [[ "${master_name}" = null ]] || [[ "${master_ip}" = null ]] 321 | then 322 | log_error "${msg}" 323 | log_error "no valid data were transmitted by our icinga2 master." 324 | 325 | exit 1 326 | fi 327 | 328 | mv /tmp/sign_${HOSTNAME}.json ${ICINGA2_LIB_DIRECTORY}/backup/ 329 | 330 | log_info "${msg}" 331 | if [[ "${DEBUG}" = "true" ]] 332 | then 333 | log_debug " - ${master_name}" 334 | log_debug " - ${master_ip}" 335 | fi 336 | 337 | sleep 5s 338 | 339 | RESTART_NEEDED="true" 340 | else 341 | status=$(echo "${code}" | jq --raw-output .status 2> /dev/null) 342 | msg=$(echo "${code}" | jq --raw-output .message 2> /dev/null) 343 | 344 | [[ "${DEBUG}" = "true" ]] && log_debug "${status}" 345 | 346 | log_error "curl result: '${result}'" 347 | log_error "${msg}" 348 | 349 | # TODO 350 | # wat nu? 351 | fi 352 | 353 | endpoint_configuration 354 | fi 355 | } 356 | -------------------------------------------------------------------------------- /rootfs/init/common.sh: -------------------------------------------------------------------------------- 1 | # 2 | 3 | version_string() { 4 | echo "${1}" | sed 's|r||' | awk -F '-' '{print $1}' 5 | } 6 | 7 | # compare the version of the Icinga2 Master with the Satellite 8 | # 9 | version_of_icinga_master() { 10 | 11 | [[ "${ICINGA2_TYPE}" = "Master" ]] && return 12 | 13 | log_info "wait for our master '${ICINGA2_MASTER}' to come up" 14 | 15 | . /init/wait_for/icinga_master.sh 16 | 17 | # get the icinga2 version of our master 18 | # 19 | # log_info "compare our version with the master '${ICINGA2_MASTER}'" 20 | code=$(curl \ 21 | --user ${CERT_SERVICE_API_USER}:${CERT_SERVICE_API_PASSWORD} \ 22 | --silent \ 23 | --insecure \ 24 | --header 'Accept: application/json' \ 25 | https://${ICINGA2_MASTER}:5665/v1/status/IcingaApplication ) 26 | 27 | if [[ $? -eq 0 ]] 28 | then 29 | version=$(echo "${code}" | jq --raw-output '.results[].status.icingaapplication.app.version' 2> /dev/null) 30 | 31 | version=$(version_string ${version}) 32 | 33 | vercomp ${version} ${ICINGA2_VERSION} 34 | case $? in 35 | 0) op='=';; 36 | 1) op='>';; 37 | 2) op='<';; 38 | esac 39 | 40 | if [[ "${op}" != "=" ]] 41 | then 42 | if [[ "${op}" = "<" ]] 43 | then 44 | log_warn "The version of the master is smaller than that of the satellite!" 45 | elif [[ "${op}" = ">" ]] 46 | then 47 | log_warn "The version of the master is higher than that of the satellite!" 48 | fi 49 | 50 | log_warn "The version of the master differs from that of the satellite! (master: ${version} / satellite: ${BUILD_VERSION})" 51 | log_warn "Which can lead to problems!" 52 | else 53 | log_info "The versions between Master and Satellite are identical" 54 | fi 55 | fi 56 | } 57 | 58 | 59 | stdbool() { 60 | 61 | if [ -z "${1}" ] 62 | then 63 | echo "n" 64 | else 65 | echo ${1:0:1} | tr '[:upper:]' '[:lower:]' 66 | fi 67 | } 68 | 69 | 70 | # prepare the system and icinga to run in the docker environment 71 | # 72 | prepare() { 73 | 74 | for p in HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy 75 | do 76 | unset "${p}" 77 | done 78 | 79 | [[ -d ${ICINGA2_LIB_DIRECTORY}/backup ]] || mkdir -p ${ICINGA2_LIB_DIRECTORY}/backup 80 | [[ -d ${ICINGA2_CERT_DIRECTORY} ]] || mkdir -p ${ICINGA2_CERT_DIRECTORY} 81 | 82 | # detect username 83 | # 84 | for u in nagios icinga 85 | do 86 | if [[ "$(getent passwd ${u})" ]] 87 | then 88 | USER="${u}" 89 | break 90 | fi 91 | done 92 | 93 | # detect groupname 94 | # 95 | for g in nagios icinga 96 | do 97 | if [[ "$(getent group ${g})" ]] 98 | then 99 | GROUP="${g}" 100 | break 101 | fi 102 | done 103 | 104 | # read (generated) icinga2.sysconfig and import environment 105 | # otherwise define variables 106 | # 107 | if [[ -f /etc/icinga2/icinga2.sysconfig ]] 108 | then 109 | ls -l /etc/icinga2/icinga2.sysconfig 110 | cat /etc/icinga2/icinga2.sysconfig 111 | 112 | . /etc/icinga2/icinga2.sysconfig 113 | 114 | ICINGA2_RUN_DIRECTORY=${ICINGA2_RUN_DIR} 115 | ICINGA2_LOG_DIRECTORY=${ICINGA2_LOG} 116 | fi 117 | 118 | # no entries, also use the icinga2 way 119 | # 120 | [[ -z ${ICINGA2_RUN_DIRECTORY} ]] && ICINGA2_RUN_DIRECTORY=$(/usr/sbin/icinga2 variable get RunDir) 121 | [[ -z ${ICINGA2_RUN_DIRECTORY} ]] && ICINGA2_RUN_DIRECTORY="/var/run" 122 | [[ -z ${ICINGA2_LOG_DIRECTORY} ]] && ICINGA2_LOG_DIRECTORY="/var/log/icinga2/icinga2.log" 123 | 124 | # change var.os from 'Linux' to 'Docker' to disable ssh-checks 125 | # 126 | [[ -f /etc/icinga2/conf.d/hosts.conf ]] && sed -i -e "s|^.*\ vars.os\ \=\ .*| vars.os = \"Docker\"|g" /etc/icinga2/conf.d/hosts.conf 127 | 128 | [[ -f /etc/icinga2/conf.d/services.conf ]] && mv /etc/icinga2/conf.d/services.conf /etc/icinga2/conf.d/services.conf-distributed 129 | [[ -f /etc/icinga2/conf.d/services.conf.docker ]] && cp /etc/icinga2/conf.d/services.conf.docker /etc/icinga2/conf.d/services.conf 130 | 131 | 132 | ## BUG? 133 | # missing NodeName? 134 | # log_debug "--------------------------------------------------" 135 | # grep NodeName /etc/icinga2/constants.conf 136 | # grep ZoneName /etc/icinga2/constants.conf 137 | # grep TicketSalt /etc/icinga2/constants.conf 138 | # log_debug "--------------------------------------------------" 139 | 140 | # set NodeName (important for the cert feature!) 141 | # 142 | sed -i \ 143 | -e "s|^.*\ NodeName\ \=\ .*|const\ NodeName\ \=\ \"${HOSTNAME}\"|g" \ 144 | -e "s|^.*\ ZoneName\ \=\ .*|const\ ZoneName\ \=\ \"${HOSTNAME}\"|g" \ 145 | -e "s|^.*\ TicketSalt\ \=\ .*|const\ TicketSalt\ \=\ \"${TICKET_SALT}\"|g" \ 146 | /etc/icinga2/constants.conf 147 | 148 | # log_debug "--------------------------------------------------" 149 | # grep NodeName /etc/icinga2/constants.conf 150 | # grep ZoneName /etc/icinga2/constants.conf 151 | # grep TicketSalt /etc/icinga2/constants.conf 152 | # log_debug "--------------------------------------------------" 153 | 154 | # create directory for the logfile and change rights 155 | # 156 | LOGDIR=$(dirname ${ICINGA2_LOG_DIRECTORY}) 157 | 158 | [[ -d ${LOGDIR} ]] || mkdir -p ${LOGDIR} 159 | 160 | chown ${USER}:${GROUP} ${LOGDIR} 161 | chmod ug+wx ${LOGDIR} 162 | find ${LOGDIR} -type f -exec chmod ug+rw {} \; 163 | 164 | # install demo data 165 | # 166 | if [[ "${DEMO_DATA}" = "true" ]] 167 | then 168 | cp -fua /init/demo /etc/icinga2/ 169 | 170 | sed \ 171 | -i \ 172 | -e \ 173 | 's|// include_recursive "demo"|include_recursive "demo"|g' \ 174 | /etc/icinga2/icinga2.conf 175 | fi 176 | 177 | cat << EOF > /etc/icinga2/features-available/mainlog.conf 178 | # https://www.icinga.com/docs/icinga2/latest/doc/09-object-types/#objecttype-filelogger 179 | object FileLogger "main-log" { 180 | severity = "notice" 181 | path = LocalStateDir + "/log/icinga2/icinga2.log" 182 | } 183 | EOF 184 | 185 | correct_rights 186 | } 187 | 188 | 189 | fix_sys_caps() { 190 | 191 | log_info "setting cap_net_raw+ep for some check scripts" 192 | 193 | local plugindir=/usr/lib/nagios/plugins 194 | 195 | # If we have setcap is installed, try setting cap_net_raw+ep, 196 | # which allows us to make our binaries working without the 197 | # setuid bit 198 | if command -v setcap > /dev/null 199 | then 200 | if setcap "cap_net_raw+ep" /bin/ping "cap_net_raw+ep" ${plugindir}/check_icmp "cap_net_bind_service=+ep cap_net_raw=+ep" ${plugindir}/check_dhcp 201 | then 202 | log_info "setcap for ping, check_icmp and check_dhcp worked!" 203 | else 204 | log_error "setcap for ping, check_icmp and check_dhcp failed, set uid bit." 205 | 206 | chmod +s \ 207 | /bin/ping \ 208 | ${plugindir}/check_icmp \ 209 | ${plugindir}/check_dhcp 210 | fi 211 | else 212 | log_warn "setcap is not installed, set uid bit" 213 | 214 | chmod +s \ 215 | /bin/ping \ 216 | ${plugindir}/check_icmp \ 217 | ${plugindir}/check_dhcp 218 | fi 219 | } 220 | 221 | 222 | # enable Icinga2 Feature 223 | # 224 | enable_icinga_feature() { 225 | 226 | local feature="${1}" 227 | 228 | if [[ $(icinga2 feature list | grep Enabled | grep -c ${feature}) -eq 0 ]] 229 | then 230 | log_info "feature ${feature} enabled" 231 | icinga2 feature enable ${feature} > /dev/null 232 | fi 233 | } 234 | 235 | # disable Icinga2 Feature 236 | # 237 | disable_icinga_feature() { 238 | 239 | local feature="${1}" 240 | 241 | if [[ $(icinga2 feature list | grep Enabled | grep -c ${feature}) -eq 1 ]] 242 | then 243 | log_info "feature ${feature} disabled" 244 | icinga2 feature disable ${feature} > /dev/null 245 | fi 246 | } 247 | 248 | # correct rights of files and directories 249 | # 250 | correct_rights() { 251 | 252 | chmod 1777 /tmp 253 | 254 | if ( [[ -z ${USER} ]] || [[ -z ${GROUP} ]] ) 255 | then 256 | log_error "no nagios or icinga user/group found!" 257 | else 258 | [[ -e /var/lib/icinga2/api/log/current ]] && rm -rf /var/lib/icinga2/api/log/current 259 | 260 | chown -R ${USER}:root /etc/icinga2 261 | chown -R ${USER}:${GROUP} /var/lib/icinga2 262 | chown -R ${USER}:${GROUP} ${ICINGA2_RUN_DIRECTORY}/icinga2 263 | chown -R ${USER}:${GROUP} ${ICINGA2_CERT_DIRECTORY} 264 | fi 265 | } 266 | 267 | random() { 268 | echo $(shuf -i 5-30 -n 1) 269 | } 270 | 271 | curl_opts() { 272 | 273 | opts="" 274 | opts="${opts} --user ${CERT_SERVICE_API_USER}:${CERT_SERVICE_API_PASSWORD}" 275 | opts="${opts} --silent" 276 | opts="${opts} --location" 277 | opts="${opts} --insecure" 278 | 279 | echo ${opts} 280 | } 281 | 282 | 283 | validate_certservice_environment() { 284 | 285 | CERT_SERVICE_BA_USER=${CERT_SERVICE_BA_USER:-"admin"} 286 | CERT_SERVICE_BA_PASSWORD=${CERT_SERVICE_BA_PASSWORD:-"admin"} 287 | CERT_SERVICE_API_USER=${CERT_SERVICE_API_USER:-""} 288 | CERT_SERVICE_API_PASSWORD=${CERT_SERVICE_API_PASSWORD:-""} 289 | CERT_SERVICE_SERVER=${CERT_SERVICE_SERVER:-"localhost"} 290 | CERT_SERVICE_PORT=${CERT_SERVICE_PORT:-"80"} 291 | CERT_SERVICE_PATH=${CERT_SERVICE_PATH:-"/"} 292 | USE_CERT_SERVICE=false 293 | 294 | # use the new Cert Service to create and get a valide certificat for distributed icinga services 295 | # 296 | if ( 297 | [[ ! -z ${CERT_SERVICE_BA_USER} ]] && 298 | [[ ! -z ${CERT_SERVICE_BA_PASSWORD} ]] && 299 | [[ ! -z ${CERT_SERVICE_API_USER} ]] && 300 | [[ ! -z ${CERT_SERVICE_API_PASSWORD} ]] 301 | ) 302 | then 303 | USE_CERT_SERVICE=true 304 | 305 | export CERT_SERVICE_BA_USER 306 | export CERT_SERVICE_BA_PASSWORD 307 | export CERT_SERVICE_API_USER 308 | export CERT_SERVICE_API_PASSWORD 309 | export CERT_SERVICE_SERVER 310 | export CERT_SERVICE_PORT 311 | export CERT_SERVICE_PATH 312 | export USE_CERT_SERVICE 313 | fi 314 | } 315 | 316 | 317 | validate_icinga_config() { 318 | 319 | log_info "validate our configuration" 320 | # test the configuration 321 | # 322 | /usr/sbin/icinga2 \ 323 | daemon \ 324 | ${ICINGA2_PARAMS} \ 325 | --validate 326 | 327 | # validation are not successful 328 | # 329 | if [[ $? -gt 0 ]] 330 | then 331 | log_error "the validation of our configuration was not successful." 332 | 333 | # validate again for debugging 334 | # 335 | /usr/sbin/icinga2 \ 336 | daemon \ 337 | --log-level debug \ 338 | --validate 339 | 340 | # log_error "remove all files under /var/lib/icinga add restart" 341 | # cat /var/log/icinga2/crash/* 342 | # cat /var/log/icinga2/* 343 | # 344 | # rm -rf /var/lib/icinga2/* 345 | # exit 1 346 | fi 347 | } 348 | -------------------------------------------------------------------------------- /rootfs/init/config_handler.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test () { 5 | # Convert all environment variables with names ending in __FILE into the content of 6 | # the file that they point at and use the name without the trailing __FILE. 7 | # This can be used to carry in Docker secrets. 8 | 9 | for VAR_NAME in $(env | grep '^GRAYLOG_[^=]\+__FILE=.\+' | sed -r 's/^(GRAYLOG_[^=]*)__FILE=.*/\1/g'); do 10 | 11 | VAR_NAME_FILE="${VAR_NAME}__FILE" 12 | 13 | if [ "${!VAR_NAME}" ]; then 14 | 15 | echo >&2 "ERROR: Both ${VAR_NAME} and ${VAR_NAME_FILE} are set but are exclusive" 16 | 17 | exit 1 18 | 19 | fi 20 | 21 | VAR_FILENAME="${!VAR_NAME_FILE}" 22 | 23 | echo "Getting secret ${VAR_NAME} from ${VAR_FILENAME}" 24 | 25 | if [ ! -r "${VAR_FILENAME}" ]; then 26 | echo >&2 "ERROR: ${VAR_FILENAME} does not exist or is not readable" 27 | 28 | exit 1 29 | fi 30 | 31 | export "${VAR_NAME}"="$(< "${VAR_FILENAME}")" 32 | 33 | unset "${VAR_NAME_FILE}" 34 | done 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /rootfs/init/configure_icinga.sh: -------------------------------------------------------------------------------- 1 | # 2 | 3 | # ICINGA2_MASTER must be an FQDN or an IP 4 | 5 | # ------------------------------------------------------------------------------------------------- 6 | 7 | # create API config file 8 | # this is needed for all instance types (master, satellite or agent) 9 | # 10 | create_api_config() { 11 | 12 | [[ -f /etc/icinga2/features-available/api.conf ]] || touch /etc/icinga2/features-available/api.conf 13 | 14 | # create api config 15 | # 16 | cat << EOF > /etc/icinga2/features-available/api.conf 17 | 18 | object ApiListener "api" { 19 | accept_config = true 20 | accept_commands = true 21 | ticket_salt = TicketSalt 22 | EOF 23 | 24 | # version 2.8 has some changes for certifiacte configuration 25 | # 26 | if [[ "${ICINGA2_MAJOR_VERSION}" = "2.7" ]] 27 | then 28 | cat << EOF >> /etc/icinga2/features-available/api.conf 29 | # look at https://www.icinga.com/docs/icinga2/latest/doc/16-upgrading-icinga-2/#upgrading-to-v28 30 | cert_path = SysconfDir + "/icinga2/pki/" + NodeName + ".crt" 31 | key_path = SysconfDir + "/icinga2/pki/" + NodeName + ".key" 32 | ca_path = SysconfDir + "/icinga2/pki/ca.crt" 33 | } 34 | EOF 35 | # < version 2.8, we must add the path to the certificate 36 | # 37 | else 38 | cat << EOF >> /etc/icinga2/features-available/api.conf 39 | } 40 | EOF 41 | fi 42 | } 43 | 44 | 45 | # ---------------------------------------------------------------------- 46 | 47 | . /init/cert/certificate_handler.sh 48 | 49 | create_api_config 50 | 51 | if [[ "${ICINGA2_TYPE}" = "Master" ]] 52 | then 53 | # configure_icinga2_master 54 | . /init/icinga_types/master.sh 55 | elif [[ "${ICINGA2_TYPE}" = "Satellite" ]] 56 | then 57 | # configure_icinga2_satellite 58 | . /init/icinga_types/satellite.sh 59 | else 60 | # configure_icinga2_agent 61 | . /init/icinga_types/agent.sh 62 | fi 63 | -------------------------------------------------------------------------------- /rootfs/init/database/mysql.sh: -------------------------------------------------------------------------------- 1 | 2 | [[ -z ${MYSQL_HOST} ]] && return 3 | 4 | MYSQL_OPTS="--host=${MYSQL_HOST} --user=${MYSQL_ROOT_USER} --password=${MYSQL_ROOT_PASS} --port=${MYSQL_PORT}" 5 | 6 | 7 | # Version compare function 8 | # 'stolen' from https://github.com/psi-4ward/docker-icinga2/blob/master/rootfs/init/mysql_setup.sh 9 | # but modifyed for /bin/sh support 10 | version_compare () { 11 | 12 | if [[ ${1} == ${2} ]] 13 | then 14 | echo '=' 15 | return 0 16 | fi 17 | 18 | left="$(echo ${1} | sed 's/\.//g')" 19 | right="$(echo ${2} | sed 's/\.//g')" 20 | 21 | if [[ ${left} -gt ${right} ]] 22 | then 23 | echo ">" 24 | return 0 25 | elif [[ ${left} -lt ${right} ]] 26 | then 27 | echo "<" 28 | return 0 29 | else 30 | echo "=" 31 | return 0 32 | fi 33 | } 34 | 35 | # create IDO database schema 36 | # 37 | create_schema() { 38 | 39 | enable_icinga_feature ido-mysql 40 | 41 | # check if database already created ... 42 | # 43 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = \"${IDO_DATABASE_NAME}\" limit 1;" 44 | 45 | status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}") 46 | 47 | if [[ $(echo "${status}" | wc -w) -eq 0 ]] 48 | then 49 | # Database isn't created 50 | # well, i do my job ... 51 | # 52 | log_info "create IDO database '${IDO_DATABASE_NAME}'" 53 | 54 | ( 55 | echo "--- create user '${IDO_DATABASE_NAME}'@'%' IDENTIFIED BY '${IDO_PASSWORD}';" 56 | echo "CREATE DATABASE IF NOT EXISTS ${IDO_DATABASE_NAME};" 57 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${IDO_DATABASE_NAME}.* TO 'icinga2'@'%' IDENTIFIED BY '${IDO_PASSWORD}';" 58 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${IDO_DATABASE_NAME}.* TO 'icinga2'@'$(hostname -i)' IDENTIFIED BY '${IDO_PASSWORD}';" 59 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${IDO_DATABASE_NAME}.* TO 'icinga2'@'$(hostname -s)' IDENTIFIED BY '${IDO_PASSWORD}';" 60 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${IDO_DATABASE_NAME}.* TO 'icinga2'@'$(hostname -f)' IDENTIFIED BY '${IDO_PASSWORD}';" 61 | echo "FLUSH PRIVILEGES;" 62 | ) | mysql ${MYSQL_OPTS} 63 | 64 | if [[ $? -eq 1 ]] 65 | then 66 | log_error "can't create database '${IDO_DATABASE_NAME}'" 67 | exit 1 68 | fi 69 | 70 | insert_schema 71 | fi 72 | } 73 | 74 | # insert database structure 75 | # 76 | insert_schema() { 77 | 78 | log_info "import IDO database schema" 79 | 80 | # create the ido schema 81 | # 82 | mysql ${MYSQL_OPTS} --force ${IDO_DATABASE_NAME} < /usr/share/icinga2-ido-mysql/schema/mysql.sql 83 | 84 | if [[ $? -gt 0 ]] 85 | then 86 | log_error "can't insert the IDO database schema" 87 | exit 1 88 | fi 89 | } 90 | 91 | # update database schema 92 | # 93 | update_schema() { 94 | 95 | # Database already created 96 | # 97 | # check database version 98 | # and install the update, when it needed 99 | # 100 | query="select version from ${IDO_DATABASE_NAME}.icinga_dbversion" 101 | db_version=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | tail -n1) 102 | 103 | if [[ -z "${db_version}" ]] 104 | then 105 | log_warn "no database version found. skip database upgrade." 106 | 107 | insert_schema 108 | update_schema 109 | else 110 | 111 | upgrape_directory="/usr/share/icinga2-ido-mysql/schema/upgrade" 112 | 113 | log_info "IDO database version: ${db_version}" 114 | 115 | for DB_UPDATE_FILE in $(ls -1 ${upgrape_directory}/*.sql) 116 | do 117 | FILE_VER=$(grep icinga_dbversion ${DB_UPDATE_FILE} | grep idoutils | cut -d ',' -f 5 | sed -e "s| ||g" -e "s|'||g") 118 | 119 | if [[ "$(version_compare ${db_version} ${FILE_VER})" = "<" ]] 120 | then 121 | log_info "apply database update '${FILE_VER}' from '${DB_UPDATE_FILE}'" 122 | 123 | mysql ${MYSQL_OPTS} --force ${IDO_DATABASE_NAME} < ${DB_UPDATE_FILE} 124 | 125 | if [[ $? -gt 0 ]] 126 | then 127 | log_error "database update ${DB_UPDATE_FILE} failed" 128 | exit 1 129 | fi 130 | fi 131 | done 132 | fi 133 | } 134 | 135 | # update database configuration 136 | # 137 | create_config() { 138 | 139 | log_info "create IDO configuration" 140 | 141 | # create the IDO configuration 142 | # 143 | 144 | cat << EOF > /etc/icinga2/features-available/ido-mysql.conf 145 | 146 | library "db_ido_mysql" 147 | 148 | object IdoMysqlConnection "ido-mysql" { 149 | user = "icinga2" 150 | password = "${IDO_PASSWORD}" 151 | host = "${MYSQL_HOST}" 152 | database = "${IDO_DATABASE_NAME}" 153 | port = "${MYSQL_PORT}" 154 | } 155 | EOF 156 | 157 | # sed -i \ 158 | # -e 's|host \= \".*\"|host \=\ \"'${MYSQL_HOST}'\"|g' \ 159 | # -e 's|port \= \".*\"|port \=\ \"'${MYSQL_PORT}'\"|g' \ 160 | # -e 's|password \= \".*\"|password \= \"'${IDO_PASSWORD}'\"|g' \ 161 | # -e 's|user =\ \".*\"|user =\ \"icinga2\"|g' \ 162 | # -e 's|database =\ \".*\"|database =\ \"'${IDO_DATABASE_NAME}'\"|g' \ 163 | # /etc/icinga2/features-available/ido-mysql.conf 164 | } 165 | 166 | . /init/wait_for/mysql.sh 167 | 168 | create_schema 169 | update_schema 170 | create_config 171 | 172 | # EOF 173 | -------------------------------------------------------------------------------- /rootfs/init/database/postgres.sh: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rootfs/init/demo/bp_cluster.conf: -------------------------------------------------------------------------------- 1 | # icingacli businessprocess process check --config mysql "MySQL Server" 2 | object Host "bp-cluster" { 3 | check_command = "dummy" 4 | vars.dummy_state = 0 5 | 6 | display_name = "Business Process Cluster" 7 | 8 | vars.bp_cluster["mysql"] = { 9 | icingacli_businessprocess_process = "MySQL Server" 10 | //icingacli_businessprocess_config = "mysql" 11 | icingacli_businessprocess_details = true 12 | } 13 | vars.bp_cluster["web"] = { 14 | icingacli_businessprocess_process = "Web Server" 15 | //icingacli_businessprocess_config = "web" 16 | icingacli_businessprocess_details = true 17 | } 18 | vars.bp_cluster["all"] = { 19 | icingacli_businessprocess_process = "All Services" 20 | //icingacli_businessprocess_config = "all" 21 | icingacli_businessprocess_details = true 22 | } 23 | } 24 | 25 | apply Service "bp-cluster-" for (bp_name => config in host.vars.bp_cluster) { 26 | check_command = "icingacli-businessprocess" 27 | 28 | display_name = config.icingacli_businessprocess_process 29 | 30 | vars += config 31 | 32 | assign where host.name == "bp-cluster" 33 | } 34 | -------------------------------------------------------------------------------- /rootfs/init/demo/bp_groups.conf: -------------------------------------------------------------------------------- 1 | object HostGroup "bp-hosts-mysql" { 2 | display_name = "BP Hosts MySQL" 3 | assign where "bp-host-mysql" in host.templates 4 | } 5 | object HostGroup "bp-hosts-web" { 6 | display_name = "BP Hosts Web" 7 | assign where "bp-host-web" in host.templates 8 | } 9 | -------------------------------------------------------------------------------- /rootfs/init/demo/bp_hosts.conf: -------------------------------------------------------------------------------- 1 | # TODO: put these constants into constants.conf 2 | const MySQLIcingaUsername = "icinga" 3 | const MySQLIcingaPassword = "icinga" 4 | 5 | # templates 6 | template Host "bp-host-mysql" { 7 | vars.mysql_health_username = MySQLIcingaUsername 8 | vars.mysql_health_password = MySQLIcingaPassword 9 | 10 | vars.bp_config["mysql-uptime"] = { 11 | bpcommand = "mysql_health" 12 | mysql_health_mode = "uptime" 13 | mysql_health_database = "icinga" 14 | } 15 | vars.bp_config["mysql-connection-time"] = { 16 | bpcommand = "mysql_health" 17 | mysql_health_mode = "connection-time" 18 | mysql_health_database = "icinga" 19 | } 20 | vars.bp_config["mysql-open-files"] = { 21 | bpcommand = "mysql_health" 22 | mysql_health_mode = "open-files" 23 | mysql_health_database = "icinga" 24 | } 25 | vars.os = "Linux" 26 | } 27 | 28 | template Host "bp-host-web" { 29 | vars.bp_config["http-response"] = { 30 | bpcommand = "http" 31 | http_uri = "/icingaweb2" 32 | } 33 | vars.bp_config["lx-load"] = { 34 | bpcommand = "load" 35 | load_wload1 = 50 36 | load_wload5 = 40 37 | load_wload15 = 30 38 | load_cload1 = 90 39 | load_cload5 = 96 40 | load_cload15 = 94 41 | } 42 | vars.os = "Windows" 43 | } 44 | 45 | # mysql 46 | object Host "c1-mysql-1" { 47 | import "bp-host-mysql" 48 | check_command = "hostalive" 49 | address = "127.0.0.1" 50 | vars.db_type = "mysql" 51 | } 52 | 53 | object Host "c2-mysql-2" { 54 | import "bp-host-mysql" 55 | check_command = "hostalive" 56 | address = "1.2.3.4" //fail 57 | vars.db_type = "mysql" 58 | } 59 | 60 | # web 61 | object Host "c1-web-1" { 62 | import "bp-host-web" 63 | import "bp-host-mysql" 64 | check_command = "hostalive" 65 | address = "127.0.0.1" 66 | vars.webserver_type = "apache" 67 | } 68 | 69 | object Host "c2-web-1" { 70 | import "bp-host-web" 71 | check_command = "hostalive" 72 | address = "1.2.3.9" //fail 73 | vars.webserver_type = "nginx" 74 | } 75 | -------------------------------------------------------------------------------- /rootfs/init/demo/bp_services.conf: -------------------------------------------------------------------------------- 1 | # generate business process config services 2 | apply Service "bp-" for (bpname => config in host.vars.bp_config) { 3 | display_name = bpname 4 | 5 | if (config.contains("bpcommand")) { 6 | check_command = config.bpcommand 7 | } else { 8 | check_command = "ping4" 9 | } 10 | 11 | check_interval = 30s 12 | retry_interval = 15s 13 | 14 | vars += config 15 | } 16 | -------------------------------------------------------------------------------- /rootfs/init/demo/cube_hosts.conf: -------------------------------------------------------------------------------- 1 | template Host "cube-generic-server" { 2 | check_command = "random" 3 | } 4 | 5 | ## production 6 | 7 | for (i in range(5)) { 8 | object Host "cube-db-" + i { 9 | import "cube-generic-server" 10 | 11 | vars.application = "database" 12 | vars.environment = "production" 13 | vars.operatingsystem = "centos" 14 | vars.location = "berlin" 15 | } 16 | } 17 | 18 | for (i in range(5,10)) { 19 | object Host "cube-db-" + i { 20 | import "cube-generic-server" 21 | 22 | vars.application = "database" 23 | vars.environment = "production" 24 | vars.operatingsystem = "debian" 25 | vars.location = "washington" 26 | } 27 | } 28 | 29 | for (i in range(5)) { 30 | object Host "cube-web-prod-" + i { 31 | import "cube-generic-server" 32 | 33 | vars.application = "webserver" 34 | vars.environment = "production" 35 | vars.operatingsystem = "centos" 36 | vars.location = "london" 37 | } 38 | } 39 | for (i in range(5,10)) { 40 | object Host "cube-web-prod-" + i { 41 | import "cube-generic-server" 42 | 43 | vars.application = "webserver" 44 | vars.environment = "production" 45 | vars.operatingsystem = "debian" 46 | vars.location = "sydney" 47 | } 48 | } 49 | ## staging 50 | 51 | for (i in range(5)) { 52 | object Host "cube-app-stage-" + i { 53 | import "cube-generic-server" 54 | 55 | vars.environment = "production" 56 | vars.application = "appserver" 57 | vars.operatingsystem = "debian" 58 | vars.location = "sydney" 59 | } 60 | } 61 | for (i in range(5,10)) { 62 | object Host "cube-app-stage-" + i { 63 | import "cube-generic-server" 64 | 65 | vars.environment = "staging" 66 | vars.application = "webserver" 67 | vars.operatingsystem = "centos" 68 | vars.location = "berlin" 69 | } 70 | } 71 | ## development 72 | 73 | for (i in range(5)) { 74 | object Host "cube-web-dev-" + i { 75 | import "cube-generic-server" 76 | 77 | vars.environment = "development" 78 | vars.application = "webserver" 79 | vars.operatingsystem = "windows" 80 | vars.location = "washington" 81 | } 82 | } 83 | for (i in range(5,10)) { 84 | object Host "cube-web-dev-" + i { 85 | import "cube-generic-server" 86 | 87 | vars.environment = "development" 88 | vars.application = "appserver" 89 | vars.operatingsystem = "debian" 90 | vars.location = "london" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /rootfs/init/demo/globe_hosts.conf: -------------------------------------------------------------------------------- 1 | const GeoLocation = { 2 | "nuremberg" = "49.425409,11.079655", 3 | "berlin" = "52.524372,13.389856", 4 | "vienna" = "48.208174,16.373819", 5 | "san francisco" = "37.774929,-122.419416", 6 | "new york" = "40.712784,-74.005941", 7 | "los angeles" = "34.052234,-118.243685", 8 | "london" = "51.507351,-0.127758", 9 | "amsterdam" = "52.370216,4.895168", 10 | "tokyo" = "35.689487,139.691706", 11 | "bangkok" = "13.756331,100.501765", 12 | } 13 | 14 | for (k => v in globals.GeoLocation) { 15 | 16 | //random number of 17 | var count = Math.floor(Math.random() * 20); 18 | 19 | for (i in range(count)) { 20 | object Host "globe-server-" + k + "-" + i use (k, v) { 21 | check_command = "random" 22 | 23 | notes = "globe host in " + k 24 | vars.geolocation = v 25 | } 26 | } 27 | } 28 | 29 | //globe module expects services with geolocation 30 | apply Service "globe" { 31 | check_command = "random" 32 | vars.geolocation = host.vars.geolocation 33 | assign where host.vars.geolocation 34 | } 35 | -------------------------------------------------------------------------------- /rootfs/init/environment.sh: -------------------------------------------------------------------------------- 1 | # 2 | # read and handle all needed environment variables 3 | # 4 | 5 | HOSTNAME=$(hostname -f) 6 | 7 | DEBUG=${DEBUG:-0} 8 | DEVELOPMENT_MODUS=${DEVELOPMENT_MODUS:-0} 9 | 10 | ICINGA2_CERT_DIRECTORY="/var/lib/icinga2/certs" 11 | ICINGA2_LIB_DIRECTORY="/var/lib/icinga2" 12 | 13 | ICINGA2_LOGLEVEL=${ICINGA2_LOGLEVEL:-"warning"} 14 | 15 | ICINGA2_MAJOR_VERSION=$(icinga2 --version | head -n1 | awk -F 'version: ' '{printf $2}' | awk -F \. {'print $1 "." $2'} | sed 's|r||') 16 | [[ "${ICINGA2_MAJOR_VERSION}" = "2.7" ]] && ICINGA2_CERT_DIRECTORY="/etc/icinga2/certs" 17 | 18 | DEMO_DATA=${DEMO_DATA:-'false'} 19 | USER= 20 | GROUP= 21 | ICINGA2_MASTER=${ICINGA2_MASTER:-} 22 | ICINGA2_PARENT=${ICINGA2_PARENT:-} 23 | 24 | ICINGA2_HOST=${ICINGA2_HOST:-${ICINGA2_MASTER}} 25 | TICKET_SALT=${TICKET_SALT:-$(pwgen -s 40 1)} 26 | 27 | BASIC_AUTH_PASS=${BASIC_AUTH_PASS:-} 28 | BASIC_AUTH_USER=${BASIC_AUTH_USER:-} 29 | 30 | MYSQL_HOST=${MYSQL_HOST:-""} 31 | MYSQL_PORT=${MYSQL_PORT:-"3306"} 32 | 33 | MYSQL_ROOT_USER=${MYSQL_ROOT_USER:-"root"} 34 | MYSQL_ROOT_PASS=${MYSQL_ROOT_PASS:-""} 35 | MYSQL_OPTS= 36 | 37 | RESTART_NEEDED="false" 38 | ADD_SATELLITE_TO_MASTER=${ADD_SATELLITE_TO_MASTER:-"true"} 39 | 40 | ICINGA2_API_USERS=${ICINGA2_API_USERS:-} 41 | 42 | if [[ "${ICINGA2_TYPE}" = "Master" ]] 43 | then 44 | IDO_DATABASE_NAME=${IDO_DATABASE_NAME:-"icinga2core"} 45 | if [[ -z ${IDO_PASSWORD} ]] 46 | then 47 | IDO_PASSWORD=$(pwgen -s 15 1) 48 | 49 | log_warn "NO IDO PASSWORD HAS BEEN SET!" 50 | log_warn "DATABASE CONNECTIONS ARE NOT RESTART SECURE!" 51 | log_warn "DYNAMICALLY GENERATED PASSWORD: '${IDO_PASSWORD}' (ONLY VALID FOR THIS SESSION)" 52 | fi 53 | 54 | # graphite service 55 | CARBON_HOST=${CARBON_HOST:-""} 56 | CARBON_PORT=${CARBON_PORT:-2003} 57 | 58 | #influxdb service 59 | INFLUXDB_HOST=${INFLUXDB_HOST:-""} 60 | INFLUXDB_PORT=${INFLUXDB_PORT:-8086} 61 | INFLUXDB_DB=${INFLUXDB_DB:-icinga2} 62 | INFLUXDB_USER=${INFLUXDB_USER:-} 63 | INFLUXDB_PASS=${INFLUXDB_PASS:-} 64 | 65 | # msmtp 66 | ICINGA2_MSMTP_RELAY_SERVER=${ICINGA2_MSMTP_RELAY_SERVER:-} 67 | ICINGA2_MSMTP_REWRITE_DOMAIN=${ICINGA2_MSMTP_REWRITE_DOMAIN:-} 68 | ICINGA2_MSMTP_RELAY_USE_STARTTLS=${ICINGA2_MSMTP_RELAY_USE_STARTTLS:-"false"} 69 | 70 | ICINGA2_MSMTP_SENDER_EMAIL=${ICINGA2_MSMTP_SENDER_EMAIL:-} 71 | ICINGA2_MSMTP_SMTPAUTH_USER=${ICINGA2_MSMTP_SMTPAUTH_USER:-} 72 | ICINGA2_MSMTP_SMTPAUTH_PASS=${ICINGA2_MSMTP_SMTPAUTH_PASS:-} 73 | ICINGA2_MSMTP_ALIASES=${ICINGA2_MSMTP_ALIASES:-} 74 | ICINGA2_MSMTP_RECV_ROOT=${ICINGA2_MSMTP_RECV_ROOT:-} 75 | ICINGA2_MSMTP_ACC_NAME=${ICINGA2_MSMTP_ACC_NAME:-} 76 | 77 | ADD_SATELLITE_TO_MASTER="false" 78 | fi 79 | 80 | 81 | # cert-service 82 | USE_CERT_SERVICE=${USE_CERT_SERVICE:-false} 83 | if [[ "${USE_CERT_SERVICE}" = "true" ]] 84 | then 85 | export CERT_SERVICE_BA_USER=${CERT_SERVICE_BA_USER:-"admin"} 86 | export CERT_SERVICE_BA_PASSWORD=${CERT_SERVICE_BA_PASSWORD:-"admin"} 87 | export CERT_SERVICE_API_USER=${CERT_SERVICE_API_USER:-""} 88 | export CERT_SERVICE_API_PASSWORD=${CERT_SERVICE_API_PASSWORD:-""} 89 | export CERT_SERVICE_SERVER=${CERT_SERVICE_SERVER:-"localhost"} 90 | export CERT_SERVICE_PORT=${CERT_SERVICE_PORT:-"80"} 91 | export CERT_SERVICE_PATH=${CERT_SERVICE_PATH:-"/"} 92 | fi 93 | 94 | [[ ${CERT_SERVICE_PORT} = *443 ]] && protocol=https || protocol=http 95 | export CERT_SERVICE_PROTOCOL=${protocol} 96 | 97 | export PKI_CMD="icinga2 pki" 98 | export PKI_KEY_FILE="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key" 99 | export PKI_CSR_FILE="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.csr" 100 | export PKI_CRT_FILE="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt" 101 | 102 | 103 | NEEDED_SERVICES="database" 104 | 105 | # ----------------------------------------------------------------------------------- 106 | 107 | # if [[ ! -z "${CONFIG_BACKEND}" ]] || [[ "${CONFIG_BACKEND}" = "consul" ]] 108 | # then 109 | # . /init/consul.sh 110 | # wait_for_consul 111 | # fi 112 | # 113 | # if [[ ! -z "${CONSUL}" ]] || [[ "${CONFIG_BACKEND}" = "consul" ]] 114 | # then 115 | # DATABASE_PASSWORD=$(get_consul_var "database/root/password") 116 | # 117 | # echo "database password: '${DATABASE_PASSWORD}'" 118 | # fi 119 | 120 | export ICINGA2_MAJOR_VERSION 121 | export ICINGA2_CERT_DIRECTORY 122 | export ICINGA2_LIB_DIRECTORY 123 | export HOSTNAME 124 | 125 | # ----------------------------------------------------------------------------------- 126 | -------------------------------------------------------------------------------- /rootfs/init/examples/cert-manager.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Example Script to create Icinga2 Certificates 4 | # 5 | # This Script is tested in a Docker Container based on Alpine with an installed supervisord! 6 | # For all others distribition, check PATH or start-stop scripts 7 | 8 | # ---------------------------------------------------------------------- 9 | 10 | # Supported commands for pki command: 11 | # * pki new-ca (sets up a new CA) 12 | # * pki new-cert (creates a new CSR) 13 | # Command options: 14 | # --cn arg Common Name 15 | # --key arg Key file path (output 16 | # --csr arg CSR file path (optional, output) 17 | # --cert arg Certificate file path (optional, output) 18 | # * pki request (requests a certificate) 19 | # Command options: 20 | # --key arg Key file path (input) 21 | # --cert arg Certificate file path (input + output) 22 | # --ca arg CA file path (output) 23 | # --trustedcert arg Trusted certificate file path (input) 24 | # --host arg Icinga 2 host 25 | # --port arg Icinga 2 port 26 | # --ticket arg Icinga 2 PKI ticket 27 | # * pki save-cert (saves another Icinga 2 instance's certificate) 28 | # Command options: 29 | # --key arg Key file path (input), obsolete 30 | # --cert arg Certificate file path (input), obsolete 31 | # --trustedcert arg Trusted certificate file path (output) 32 | # --host arg Icinga 2 host 33 | # --port arg (=5665) Icinga 2 port 34 | # * pki sign-csr (signs a CSR) 35 | # Command options: 36 | # --csr arg CSR file path (input) 37 | # --cert arg Certificate file path (output) 38 | # * pki ticket (generates a ticket) 39 | # Command options: 40 | # --cn arg Certificate common name 41 | # --salt arg Ticket salt 42 | 43 | # ---------------------------------------------------------------------- 44 | 45 | HOSTNAME="$(hostname -f)" 46 | DOMAINNAME="$(hostname -d)" 47 | 48 | PKI_KEY="/etc/icinga2/pki/${HOSTNAME}.key" 49 | PKI_CSR="/etc/icinga2/pki/${HOSTNAME}.csr" 50 | PKI_CRT="/etc/icinga2/pki/${HOSTNAME}.crt" 51 | 52 | ICINGA2_MASTER="icinga2-master" 53 | 54 | PKI_CMD="icinga2 pki" 55 | 56 | # -------------------------------------------------------------------------------------------- 57 | 58 | chown -R icinga: /var/lib/icinga2 59 | 60 | icinga2 api setup 61 | 62 | ${PKI_CMD} new-cert \ 63 | --cn ${HOSTNAME} \ 64 | --key ${PKI_KEY} \ 65 | --csr ${PKI_CSR} 66 | 67 | ${PKI_CMD} sign-csr \ 68 | --csr ${PKI_CSR} \ 69 | --cert ${PKI_CRT} 70 | 71 | 72 | supervisorctl restart icinga2 73 | 74 | echo -e "\n\n" 75 | 76 | SATELLITES="icinga2-satellite-1 icinga2-satellite-2" 77 | 78 | for s in ${SATELLITES} 79 | do 80 | dir="/tmp/${s}" 81 | 82 | chown icinga: ${dir} 83 | 84 | salt=$(echo ${s} | sha256sum | cut -f 1 -d ' ') 85 | 86 | mkdir ${dir} 87 | 88 | 89 | ${PKI_CMD} new-cert \ 90 | --cn ${s} \ 91 | --key ${dir}/${s}.key \ 92 | --csr ${dir}/${s}.csr 93 | 94 | ${PKI_CMD} sign-csr \ 95 | --csr ${dir}/${s}.csr \ 96 | --cert ${dir}/${s}.crt 97 | 98 | ${PKI_CMD} save-cert \ 99 | --key ${dir}/${s}.key \ 100 | --cert ${dir}/${s}.crt \ 101 | --trustedcert ${dir}/trusted-master.crt \ 102 | --host ${ICINGA2_MASTER} 103 | 104 | # Receive Ticket from master... 105 | pki_ticket=$(${PKI_CMD} ticket \ 106 | --cn ${HOSTNAME} \ 107 | --salt ${salt}) 108 | 109 | ${PKI_CMD} request \ 110 | --host ${ICINGA2_MASTER} \ 111 | --port 5665 \ 112 | --ticket ${pki_ticket} \ 113 | --key ${dir}/${s}.key \ 114 | --cert ${dir}/${s}.crt \ 115 | --trustedcert ${dir}/trusted-master.crt \ 116 | --ca /etc/icinga2/pki/ca.crt 117 | 118 | # openssl x509 -in ${dir}/${s}.crt -text -noout 119 | # openssl req -in ${dir}/${s}.csr -noout -text 120 | 121 | done 122 | 123 | exit 0 124 | -------------------------------------------------------------------------------- /rootfs/init/examples/certificate_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /etc/profile 4 | 5 | . /init/output.sh 6 | . /init/environment.sh 7 | 8 | certificate_with_ticket() { 9 | 10 | [[ -d ${ICINGA2_CERT_DIRECTORY} ]] || mkdir -p ${ICINGA2_CERT_DIRECTORY} 11 | 12 | chmod a+w ${ICINGA2_CERT_DIRECTORY} 13 | 14 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] 15 | then 16 | return 17 | fi 18 | 19 | # create an ticket on the master via: 20 | # icinga2 pki ticket --cn ${HOSTNAME} 21 | 22 | [[ "${DEBUG}" = "true" ]] && log_debug "ask for an PKI ticket" 23 | ticket=$(curl \ 24 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 25 | --silent \ 26 | --location \ 27 | --insecure \ 28 | --request GET \ 29 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 30 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 31 | "${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}/v2/ticket/${HOSTNAME}") 32 | 33 | # enable neccessary features 34 | # icinga2 feature enable api compatlog command 35 | 36 | # the following commands are copied out of the icinga2-documentation 37 | [[ "${DEBUG}" = "true" ]] && log_debug "pki new-cert" 38 | icinga2 pki new-cert \ 39 | --log-level ${ICINGA2_LOGLEVEL} \ 40 | --cn ${HOSTNAME} \ 41 | --key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key \ 42 | --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt 43 | 44 | [[ "${DEBUG}" = "true" ]] && log_debug "pki save-cert" 45 | icinga2 pki save-cert \ 46 | --log-level ${ICINGA2_LOGLEVEL} \ 47 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt \ 48 | --host ${ICINGA2_MASTER} 49 | 50 | [[ "${DEBUG}" = "true" ]] && log_debug "pki request" 51 | icinga2 pki request \ 52 | --log-level ${ICINGA2_LOGLEVEL} \ 53 | --host ${ICINGA2_MASTER} \ 54 | --port ${ICINGA2_MASTER_PORT} \ 55 | --ticket ${ticket} \ 56 | --key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key \ 57 | --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt \ 58 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt \ 59 | --ca ${ICINGA2_CERT_DIRECTORY}/ca.crt 60 | 61 | #--endpoint ${ICINGA2_MASTER} \ # ,${ICINGA2_MASTER},${ICINGA2_MASTER_PORT} \ 62 | 63 | [[ "${DEBUG}" = "true" ]] && log_debug "node setup" 64 | icinga2 node setup \ 65 | --log-level ${ICINGA2_LOGLEVEL} \ 66 | --accept-config \ 67 | --accept-commands \ 68 | --disable-confd \ 69 | --cn ${HOSTNAME} \ 70 | --zone ${HOSTNAME} \ 71 | --endpoint ${ICINGA2_MASTER} \ 72 | --parent_host ${ICINGA2_MASTER} \ 73 | --parent_zone master \ 74 | --ticket ${ticket} \ 75 | --trustedcert ${ICINGA2_CERT_DIRECTORY}/trusted-master.crt 76 | 77 | date="$(date "+%Y-%m-%d %H:%M:%S")" 78 | timestamp="$(date "+%s")" 79 | 80 | cat << EOF > ${ICINGA2_LIB_DIRECTORY}/backup/sign_${HOSTNAME}.json 81 | { 82 | "status": 200, 83 | "message": "PKI for ${HOSTNAME}", 84 | "master_name": "${ICINGA2_MASTER}", 85 | "master_ip": "", 86 | "date": "${date}", 87 | "timestamp": ${timestamp} 88 | } 89 | EOF 90 | } 91 | 92 | 93 | 94 | get_certificate_for_the_satellite() { 95 | 96 | local WORK_DIR=/tmp 97 | 98 | validate_local_ca 99 | 100 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] && [[ ${ICINGA2_CERT_DIRECTORY}/ca.crt ]] 101 | then 102 | return 103 | fi 104 | 105 | # 106 | # if [ -f ${ICINGA_CERT_DIR}/${HOSTNAME}.key ] 107 | # then 108 | # return 109 | # fi 110 | 111 | # if [ ${ICINGA_CERT_SERVICE} ] 112 | # then 113 | log_info "we ask our cert-service for a certificate .." 114 | 115 | set -x 116 | code=$(curl \ 117 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 118 | --silent \ 119 | --location \ 120 | --insecure \ 121 | --request GET \ 122 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/icinga-version) 123 | 124 | log_debug "remote icinga version: ${code}" 125 | 126 | # generate a certificate request 127 | # 128 | code=$(curl \ 129 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 130 | --silent \ 131 | --insecure \ 132 | --request GET \ 133 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 134 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 135 | --write-out "%{http_code}\n" \ 136 | --output /tmp/request_${HOSTNAME}.json \ 137 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/request/${HOSTNAME}) 138 | 139 | if ( [ $? -eq 0 ] && [ ${code} -eq 200 ] ) 140 | then 141 | 142 | log_info "certifiacte request was successful" 143 | log_info "download and install the certificate" 144 | 145 | master_name=$(jq --raw-output .master_name /tmp/request_${HOSTNAME}.json) 146 | checksum=$(jq --raw-output .checksum /tmp/request_${HOSTNAME}.json) 147 | 148 | cat /tmp/request_${HOSTNAME}.json 149 | 150 | # rm -f /tmp/request_${HOSTNAME}.json 151 | 152 | mkdir -p ${WORK_DIR}/pki/${HOSTNAME} 153 | 154 | # get our created cert 155 | # 156 | code=$(curl \ 157 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 158 | --silent \ 159 | --insecure \ 160 | --request GET \ 161 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 162 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 163 | --header "X-CHECKSUM: ${checksum}" \ 164 | --write-out "%{http_code}\n" \ 165 | --output ${WORK_DIR}/pki/${HOSTNAME}/${HOSTNAME}.tgz \ 166 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/cert/${HOSTNAME}) 167 | 168 | result="${?}" 169 | 170 | if [[ ${result} -eq 0 ]] && [[ ${code} -eq 200 ]] 171 | then 172 | 173 | cd ${WORK_DIR}/pki/${HOSTNAME} 174 | 175 | # the download has not working 176 | # 177 | if [[ ! -f ${HOSTNAME}.tgz ]] 178 | then 179 | log_error "cert File '${HOSTNAME}.tgz' not found!" 180 | exit 1 181 | fi 182 | 183 | tar -xzf ${HOSTNAME}.tgz 184 | 185 | ls -lth 186 | 187 | if [[ ! -f ${HOSTNAME}.pem ]] 188 | then 189 | cat ${HOSTNAME}.crt ${HOSTNAME}.key >> ${HOSTNAME}.pem 190 | fi 191 | 192 | cp -a ${HOSTNAME}.crt ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt 193 | cp -a ${HOSTNAME}.key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key 194 | cp -a ${HOSTNAME}.pem ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem 195 | cp -a ca.crt ${ICINGA2_CERT_DIRECTORY}/ca.crt 196 | 197 | cp -a /tmp/request_${HOSTNAME}.json /var/lib/icinga2/backup/sign_${HOSTNAME}.json 198 | 199 | # store the master for later restart 200 | # 201 | echo "${master_name}" > ${WORK_DIR}/pki/${HOSTNAME}/master 202 | 203 | create_api_config 204 | 205 | else 206 | log_error "can't download our certificate!" 207 | 208 | rm -rf ${WORK_DIR}/pki 2> /dev/null 209 | 210 | unset ICINGA_API_PKI_PATH 211 | fi 212 | else 213 | 214 | error=$(cat /tmp/request_${HOSTNAME}.json) 215 | 216 | log_error "${code} - the cert-service tell us a problem: '${error}'" 217 | log_error "exit ..." 218 | 219 | rm -f /tmp/request_${HOSTNAME}.json 220 | 221 | exit 1 222 | fi 223 | set +x 224 | 225 | # fi 226 | } 227 | 228 | 229 | 230 | request_certificate_from_master() { 231 | 232 | # we have a certificate 233 | # restore our own zone configuration 234 | # otherwise, we can't communication with the master 235 | # 236 | if ( [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] && [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ]] ) 237 | then 238 | : 239 | else 240 | # no certificate found 241 | # use the node wizard to create a valid certificate request 242 | # 243 | 244 | log_info "use the node wizard to create a valid certificate request" 245 | expect /init/node-wizard.expect 1> /dev/null 246 | 247 | result=${?} 248 | 249 | if [[ "${DEBUG}" = "true" ]] 250 | then 251 | log_debug "the result for the node-wizard was '${result}'" 252 | fi 253 | 254 | # after this, in /var/lib/icinga2/certs/ should be found this files: 255 | # - ca.crt 256 | # - $(hostname -f).key 257 | # - $(hostname -f).crt 258 | # 259 | # these files are absolutly importand for the nexts steps 260 | # we can abort immediately, if it should come to mistakes. 261 | 262 | sleep 8s 263 | 264 | # check transfered certificate files 265 | # 266 | BREAK="false" 267 | for f in ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt ${ICINGA2_CERT_DIRECTORY}/ca.crt 268 | do 269 | if [[ -f ${f} ]] 270 | then 271 | : 272 | [[ "${DEBUG}" = "true" ]] && log_debug "file '${f}' exists!" 273 | else 274 | log_error "file '${f}' is missing!" 275 | BREAK="true" 276 | fi 277 | done 278 | 279 | if [[ ${BREAK} = "true" ]] 280 | then 281 | 282 | if [[ ! -f ${ICINGA2_CERT_DIRECTORY}/ca.crt ]] 283 | then 284 | get_ca_file 285 | fi 286 | fi 287 | 288 | # and now we have to ask our master to confirm this certificate 289 | # 290 | log_info "ask our cert-service to sign our certifiacte" 291 | 292 | . /init/wait_for/cert_service.sh 293 | 294 | code=$(curl \ 295 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 296 | --silent \ 297 | --location \ 298 | --insecure \ 299 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 300 | --header "X-API-PASSWORD: ${CERT_SERVICE_API_PASSWORD}" \ 301 | --write-out "%{http_code}\n" \ 302 | --output /tmp/sign_${HOSTNAME}.json \ 303 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/sign/${HOSTNAME}) 304 | 305 | result=${?} 306 | 307 | if [[ "${DEBUG}" = "true" ]] 308 | then 309 | log_debug "result for sign certificate:" 310 | log_debug "result: '${result}' | code: '${code}'" 311 | log_debug "$(ls -lth /tmp/sign_${HOSTNAME}.json)" 312 | fi 313 | 314 | if [[ ${result} -eq 0 ]] && [[ ${code} == 200 ]] 315 | then 316 | msg=$(jq --raw-output .message /tmp/sign_${HOSTNAME}.json 2> /dev/null) 317 | master_name=$(jq --raw-output .master_name /tmp/sign_${HOSTNAME}.json 2> /dev/null) 318 | master_ip=$(jq --raw-output .master_ip /tmp/sign_${HOSTNAME}.json 2> /dev/null) 319 | 320 | if [[ "${master_name}" = null ]] || [[ "${master_ip}" = null ]] 321 | then 322 | log_error "${msg}" 323 | log_error "no valid data were transmitted by our icinga2 master." 324 | 325 | exit 1 326 | fi 327 | 328 | mv /tmp/sign_${HOSTNAME}.json ${ICINGA2_LIB_DIRECTORY}/backup/ 329 | 330 | log_info "${msg}" 331 | if [[ "${DEBUG}" = "true" ]] 332 | then 333 | log_debug " - ${master_name}" 334 | log_debug " - ${master_ip}" 335 | fi 336 | 337 | sleep 5s 338 | 339 | RESTART_NEEDED="true" 340 | else 341 | status=$(echo "${code}" | jq --raw-output .status 2> /dev/null) 342 | msg=$(echo "${code}" | jq --raw-output .message 2> /dev/null) 343 | 344 | [[ "${DEBUG}" = "true" ]] && log_debug "${status}" 345 | 346 | log_error "curl result: '${result}'" 347 | log_error "${msg}" 348 | 349 | # TODO 350 | # wat nu? 351 | fi 352 | 353 | endpoint_configuration 354 | fi 355 | } 356 | -------------------------------------------------------------------------------- /rootfs/init/examples/create certificate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR="/tmp/icinga-pki/xxxxxx" 4 | 5 | SATELLITE="icinga2-satellite-2.matrix.lan" 6 | SALT=$(echo ${s} | sha256sum | cut -f 1 -d ' ') 7 | 8 | ICINGA2_CERT_DIRECTORY="/etc/icinga2/pki" 9 | ICINGA2_VERSION=$(icinga2 --version | head -n1 | awk -F 'version: ' '{printf $2}' | awk -F \. {'print $1 "." $2'} | sed 's|r||') 10 | [ "${ICINGA2_VERSION}" = "2.8" ] && ICINGA2_CERT_DIRECTORY="/var/lib/icinga2/certs" 11 | 12 | [ -d ${DIR} ] && rm -rf ${DIR} 13 | [ -d ${DIR} ] || mkdir -vp ${DIR} 14 | 15 | chown icinga: ${DIR} 16 | 17 | icinga2 pki new-cert \ 18 | --cn ${SATELLITE} \ 19 | --key ${DIR}/${SATELLITE}.key \ 20 | --csr ${DIR}/${SATELLITE}.csr 21 | 22 | icinga2 pki sign-csr \ 23 | --csr ${DIR}/${SATELLITE}.csr \ 24 | --cert ${DIR}/${SATELLITE}.crt 25 | 26 | icinga2 pki save-cert \ 27 | --key ${DIR}/${SATELLITE}.key \ 28 | --cert ${DIR}/${SATELLITE}.crt \ 29 | --trustedcert ${DIR}/trusted-master.crt \ 30 | --host icinga2-master.matrix.lan 31 | 32 | ticket=$(icinga2 pki ticket \ 33 | --cn icinga2-master.matrix.lan \ 34 | --salt ${SALT}) 35 | 36 | icinga2 pki request \ 37 | --host icinga2-master.matrix.lan \ 38 | --port 5665 \ 39 | --ticket ${ticket} \ 40 | --key ${DIR}/${SATELLITE}.key \ 41 | --cert ${DIR}/${SATELLITE}.crt \ 42 | --trustedcert ${DIR}/trusted-master.crt \ 43 | --ca ${ICINGA2_CERT_DIRECTORY}/ca.crt 44 | 45 | -------------------------------------------------------------------------------- /rootfs/init/examples/iowatch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | sigint_handler() { 4 | 5 | pkill -15 $(cat /tmp/dnsmasq.pid) 6 | exit 7 | } 8 | 9 | trap sigint_handler SIGINT QUIT KILL 10 | 11 | start() { 12 | 13 | touch /app/dnsmasq.addn.docker 14 | chmod a+rw /app/dnsmasq.addn.docker 15 | 16 | /usr/sbin/dnsmasq --user=root --pid-file=/tmp/dnsmasq.pid --log-facility=/tmp/dnsmasq.log 17 | } 18 | 19 | start 20 | 21 | while true 22 | do 23 | $@ & 24 | PID=$! 25 | inotifywait -e modify -e move -e create -e delete /app/dnsmasq.addn.docker 26 | 27 | pkill -HUP -P $(cat /tmp/dnsmasq.pid) 28 | done 29 | 30 | 31 | # EOF 32 | -------------------------------------------------------------------------------- /rootfs/init/examples/master-key.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Example Script to create Icinga2 Certificates 4 | # 5 | # This Script is tested in a Docker Container based on Alpine with an installed supervisord! 6 | # For all others distribition, check PATH or start-stop scripts 7 | 8 | # ---------------------------------------------------------------------- 9 | 10 | # Supported commands for pki command: 11 | # * pki new-ca (sets up a new CA) 12 | # * pki new-cert (creates a new CSR) 13 | # Command options: 14 | # --cn arg Common Name 15 | # --key arg Key file path (output 16 | # --csr arg CSR file path (optional, output) 17 | # --cert arg Certificate file path (optional, output) 18 | # * pki request (requests a certificate) 19 | # Command options: 20 | # --key arg Key file path (input) 21 | # --cert arg Certificate file path (input + output) 22 | # --ca arg CA file path (output) 23 | # --trustedcert arg Trusted certificate file path (input) 24 | # --host arg Icinga 2 host 25 | # --port arg Icinga 2 port 26 | # --ticket arg Icinga 2 PKI ticket 27 | # * pki save-cert (saves another Icinga 2 instance's certificate) 28 | # Command options: 29 | # --key arg Key file path (input), obsolete 30 | # --cert arg Certificate file path (input), obsolete 31 | # --trustedcert arg Trusted certificate file path (output) 32 | # --host arg Icinga 2 host 33 | # --port arg (=5665) Icinga 2 port 34 | # * pki sign-csr (signs a CSR) 35 | # Command options: 36 | # --csr arg CSR file path (input) 37 | # --cert arg Certificate file path (output) 38 | # * pki ticket (generates a ticket) 39 | # Command options: 40 | # --cn arg Certificate common name 41 | # --salt arg Ticket salt 42 | 43 | # ---------------------------------------------------------------------- 44 | 45 | HOSTNAME="$(hostname -f)" 46 | DOMAINNAME="$(hostname -d)" 47 | 48 | ICINGA2_CERT_DIRECTORY="/etc/icinga2/pki" 49 | ICINGA2_VERSION=$(icinga2 --version | head -n1 | awk -F 'version: ' '{printf $2}' | awk -F \. {'print $1 "." $2'} | sed 's|r||') 50 | [ "${ICINGA2_VERSION}" = "2.8" ] && ICINGA2_CERT_DIRECTORY="/var/lib/icinga2/certs" 51 | 52 | export ICINGA2_VERSION 53 | export ICINGA2_CERT_DIRECTORY 54 | 55 | 56 | PKI_KEY="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key" 57 | PKI_CSR="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.csr" 58 | PKI_CRT="${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.crt" 59 | 60 | ICINGA2_MASTER="icinga2-master" 61 | 62 | PKI_CMD="icinga2 pki" 63 | 64 | killall icinga2 65 | 66 | # -------------------------------------------------------------------------------------------- 67 | 68 | chown -R icinga: /var/lib/icinga2 69 | chown -R icinga: /run/icinga2 70 | 71 | icinga2 api setup 72 | 73 | cd /tmp 74 | 75 | ${PKI_CMD} new-cert \ 76 | --cn ${HOSTNAME} \ 77 | --key ${PKI_KEY} \ 78 | --csr ${PKI_CSR} 79 | 80 | ${PKI_CMD} sign-csr \ 81 | --csr ${PKI_CSR} \ 82 | --cert ${PKI_CRT} 83 | 84 | icinga2 daemon --validate 85 | 86 | 87 | icinga2 daemon --daemonize 88 | 89 | echo -e "\n\n" 90 | 91 | SATELLITES="icinga2-satellite-1 icinga2-satellite-2" 92 | 93 | # for node in icinga2-master1.localdomain icinga2-master2.localdomain icinga2-satellite1.localdomain; do 94 | # icinga2 pki new-cert --cn $node --csr $node.csr --key $node.key 95 | # done 96 | # for node in icinga2-master1.localdomain icinga2-master2.localdomain icinga2-satellite1.localdomain; do 97 | #icinga2 pki sign-csr --csr $node.csr --cert $node.crt; 98 | # done 99 | set -x 100 | for s in ${SATELLITES} 101 | do 102 | dir="/tmp/${s}" 103 | 104 | mkdir ${dir} 105 | 106 | chown icinga: ${dir} 107 | 108 | salt=$(echo ${s} | sha256sum | cut -f 1 -d ' ') 109 | 110 | ${PKI_CMD} new-cert \ 111 | --cn ${s} \ 112 | --key ${dir}/${s}.key \ 113 | --csr ${dir}/${s}.csr 114 | 115 | ${PKI_CMD} sign-csr \ 116 | --csr ${dir}/${s}.csr \ 117 | --cert ${dir}/${s}.crt 118 | 119 | ${PKI_CMD} save-cert \ 120 | --key ${dir}/${s}.key \ 121 | --cert ${dir}/${s}.crt \ 122 | --trustedcert ${dir}/trusted-master.crt \ 123 | --host ${ICINGA2_MASTER} 124 | 125 | # Receive Ticket from master... 126 | pki_ticket=$(${PKI_CMD} ticket \ 127 | --cn ${HOSTNAME} \ 128 | --salt ${salt}) 129 | 130 | ${PKI_CMD} request \ 131 | --host ${ICINGA2_MASTER} \ 132 | --port 5665 \ 133 | --ticket ${pki_ticket} \ 134 | --key ${dir}/${s}.key \ 135 | --cert ${dir}/${s}.crt \ 136 | --trustedcert ${dir}/trusted-master.crt \ 137 | --ca ${ICINGA2_CERT_DIRECTORY}/ca.crt 138 | 139 | # openssl x509 -in ${dir}/${s}.crt -text -noout 140 | # openssl req -in ${dir}/${s}.csr -noout -text 141 | 142 | done 143 | 144 | exit 0 145 | -------------------------------------------------------------------------------- /rootfs/init/examples/node-wizard.expect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect 2 | 3 | # works for 2.10.x 4 | 5 | # exp_internal 1 6 | 7 | log_user 1 8 | set timeout 3 9 | 10 | spawn icinga2 node wizard 11 | 12 | expect -re "Please specify if this is a satellite/client setup" { 13 | send -- "y\r" 14 | } 15 | 16 | expect -re "Please specify the common name " { 17 | send -- "[exec hostname -f]\r" 18 | } 19 | 20 | expect -re "Master/Satellite Common Name" { 21 | send -- "$env(ICINGA2_MASTER)\r" 22 | } 23 | 24 | expect -re "Do you want to establish a connection to the parent node" { 25 | send -- "y\r" 26 | } 27 | 28 | expect -re "endpoint host" { 29 | send -- "$env(ICINGA2_MASTER)\r" 30 | } 31 | 32 | expect -re "endpoint port" { 33 | send -- "5665\r" 34 | } 35 | 36 | expect -re "Add more master/satellite endpoints" { 37 | send -- "n\r" 38 | } 39 | 40 | expect -re "Is this information correct" { 41 | send -- "y\r" 42 | } 43 | 44 | expect -re "Please specify the request ticket generated on your Icinga 2 master" { 45 | send -- "\r" 46 | } 47 | 48 | expect -re "Bind Host" { 49 | send -- "\r" 50 | } 51 | 52 | expect -re "Bind Port" { 53 | send -- "\r" 54 | } 55 | 56 | expect -re "config from parent node" { 57 | send -- "y\r" 58 | } 59 | 60 | expect -re "commands from parent node" { 61 | send -- "y\r" 62 | } 63 | 64 | expect -re "Local zone name " { 65 | send -- "\r" 66 | } 67 | 68 | expect -re "Parent zone name " { 69 | send -- "\r" 70 | } 71 | 72 | expect -re "you want to specify additional global zones" { 73 | send -- "n\r" 74 | } 75 | 76 | expect -re "disable the inclusion of the conf.d directory " { 77 | send -- "n\r" 78 | } 79 | 80 | interact 81 | -------------------------------------------------------------------------------- /rootfs/init/examples/use_cert-service.sh: -------------------------------------------------------------------------------- 1 | 2 | # useful for Icinga2 <2.8 3 | 4 | # generate a certificate request 5 | # 6 | code=$(curl \ 7 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 8 | --silent \ 9 | --request GET \ 10 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 11 | --header "X-API-KEY: ${CERT_SERVICE_API_PASSWORD}" \ 12 | --write-out "%{http_code}\n" \ 13 | --output /tmp/request_${HOSTNAME}.json \ 14 | http://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/request/${HOSTNAME}) 15 | 16 | master_name=$(jq --raw-output .master_name /tmp/request_${HOSTNAME}.json) 17 | checksum=$(jq --raw-output .checksum /tmp/request_${HOSTNAME}.json) 18 | 19 | # get our created cert 20 | # 21 | code=$(curl \ 22 | --user ${CERT_SERVICE_BA_USER}:${CERT_SERVICE_BA_PASSWORD} \ 23 | --silent \ 24 | --request GET \ 25 | --header "X-API-USER: ${CERT_SERVICE_API_USER}" \ 26 | --header "X-API-KEY: ${CERT_SERVICE_API_PASSWORD}" \ 27 | --header "X-CHECKSUM: ${checksum}" \ 28 | --write-out "%{http_code}\n" \ 29 | --request GET \ 30 | --output ${WORK_DIR}/pki/${HOSTNAME}/${HOSTNAME}.tgz \ 31 | http://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/cert/${HOSTNAME}) 32 | -------------------------------------------------------------------------------- /rootfs/init/healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pid=$(ps ax -o pid,args | grep -v grep | grep icinga2 | grep daemon | awk '{print $1}') 4 | 5 | if [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] 6 | then 7 | # test the configuration 8 | # 9 | /usr/sbin/icinga2 \ 10 | daemon \ 11 | --log-level critical \ 12 | --validate 13 | 14 | # validation are not successful 15 | # 16 | if [[ $? -gt 0 ]] 17 | then 18 | echo "the validation of our configuration was not successful." 19 | exit 1 20 | fi 21 | 22 | exit 0 23 | fi 24 | 25 | exit 2 26 | -------------------------------------------------------------------------------- /rootfs/init/icinga_types/agent.sh: -------------------------------------------------------------------------------- 1 | 2 | # configure a icinga2 agent instance 3 | # 4 | configure_icinga2_agent() { 5 | 6 | log_info "we are an agent .." 7 | 8 | # TODO 9 | } 10 | 11 | configure_icinga2_agent 12 | -------------------------------------------------------------------------------- /rootfs/init/icinga_types/master.sh: -------------------------------------------------------------------------------- 1 | 2 | # restore a old zone file for automatic generated satellites 3 | # 4 | restore_backup() { 5 | 6 | cp_opts="--archive --force --recursive" 7 | [[ "${DEBUG}" = "true" ]] && cp_opts="${cp_opts} --verbose" 8 | 9 | # backwards compatibility 10 | # in an older version, we create all zone config files in an seperate directory 11 | # 12 | [[ -d ${ICINGA2_LIB_DIRECTORY}/backup/automatic-zones.d ]] && mv ${ICINGA2_LIB_DIRECTORY}/backup/automatic-zones.d ${ICINGA2_LIB_DIRECTORY}/backup/zones.d 13 | 14 | if [[ -d ${ICINGA2_LIB_DIRECTORY}/backup ]] 15 | then 16 | log_info "restore backup" 17 | 18 | if [[ "${DEBUG}" = "true" ]] 19 | then 20 | if [[ -e ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf ]] 21 | then 22 | grep -nrB2 "object Endpoint" ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf 23 | fi 24 | 25 | if [[ -e ${ICINGA2_LIB_DIRECTORY}/backup/zones.d ]] 26 | then 27 | grep -nrB2 "object Endpoint" ${ICINGA2_LIB_DIRECTORY}/backup/zones.d/* 28 | fi 29 | fi 30 | 31 | if [[ -f ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf ]] 32 | then 33 | [[ "${DEBUG}" = "true" ]] && log_debug " - zones.conf" 34 | cp ${cp_opts} ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf /etc/icinga2/zones.conf 35 | fi 36 | 37 | if [[ -d ${ICINGA2_LIB_DIRECTORY}/backup/zones.d ]] 38 | then 39 | cp ${cp_opts} ${ICINGA2_LIB_DIRECTORY}/backup/zones.d/* /etc/icinga2/zones.d/ 40 | fi 41 | 42 | if [[ -f ${ICINGA2_LIB_DIRECTORY}/backup/conf.d/api-users.conf ]] 43 | then 44 | [[ "${DEBUG}" = "true" ]] && log_debug " - api-users.conf" 45 | cp ${cp_opts} ${ICINGA2_LIB_DIRECTORY}/backup/conf.d/api-users.conf /etc/icinga2/conf.d/api-users.conf 46 | fi 47 | 48 | fi 49 | } 50 | 51 | 52 | # copy master specific configurations 53 | # 54 | copy_master_specific_configurations() { 55 | 56 | # if [[ -f /etc/icinga2/zones.conf ]] && [[ -f /etc/icinga2/zones.conf-docker ]] 57 | # then 58 | # cp ${cp_opts} /etc/icinga2/zones.conf-docker /etc/icinga2/zones.conf 59 | # fi 60 | 61 | if [[ -d /etc/icinga2/zones.d/global-templates ]] 62 | then 63 | [[ "${DEBUG}" = "true" ]] && log_debug "copy global-templates" 64 | 65 | if [[ -f /etc/icinga2/master.d/templates_services.conf ]] 66 | then 67 | [[ "${DEBUG}" = "true" ]] && log_debug " - templates_services.conf" 68 | cp ${cp_opts} /etc/icinga2/master.d/templates_services.conf /etc/icinga2/zones.d/global-templates/ 69 | fi 70 | 71 | if [[ -f /etc/icinga2/satellite.d/services.conf ]] 72 | then 73 | [[ "${DEBUG}" = "true" ]] && log_debug " - services.conf" 74 | cp ${cp_opts} /etc/icinga2/satellite.d/services.conf /etc/icinga2/zones.d/global-templates/ 75 | fi 76 | fi 77 | 78 | if [[ -f /etc/icinga2/master.d/satellite_services.conf ]] 79 | then 80 | [[ "${DEBUG}" = "true" ]] && log_debug "copy master.d/satellite_services.conf" 81 | cp ${cp_opts} /etc/icinga2/master.d/satellite_services.conf /etc/icinga2/conf.d/ 82 | fi 83 | 84 | if [[ -f /etc/icinga2/satellite.d/commands.conf ]] 85 | then 86 | [[ "${DEBUG}" = "true" ]] && log_debug "copy satellite.d/commands.conf" 87 | cp ${cp_opts} /etc/icinga2/satellite.d/commands.conf /etc/icinga2/conf.d/satellite_commands.conf 88 | fi 89 | } 90 | 91 | 92 | # configure a icinga2 master instance 93 | # 94 | configure_icinga2_master() { 95 | 96 | enable_icinga_feature api 97 | 98 | create_ca 99 | 100 | [[ -d /etc/icinga2/satellites.d ]] || mkdir /etc/icinga2/satellites.d 101 | 102 | sed -i \ 103 | -e 's|// include_recursive "satellites.d"|include_recursive "satellites.d"|' \ 104 | /etc/icinga2/icinga2.conf 105 | 106 | restore_backup 107 | 108 | copy_master_specific_configurations 109 | } 110 | 111 | configure_icinga2_master 112 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/graphite.sh: -------------------------------------------------------------------------------- 1 | 2 | # configure the Graphite Support 3 | # 4 | 5 | if ( [[ -z ${CARBON_HOST} ]] || [[ -z ${CARBON_PORT} ]] ) 6 | then 7 | log_info "no settings for graphite feature found" 8 | unset CARBON_HOST 9 | unset CARBON_PORT 10 | return 11 | fi 12 | 13 | configure_graphite() { 14 | 15 | enable_icinga_feature graphite 16 | 17 | config_file="/etc/icinga2/features-enabled/graphite.conf" 18 | 19 | # create (overwrite existing) configuration 20 | # 21 | if [[ -e "${config_file}" ]] 22 | then 23 | cat > "${config_file}" <<-EOF 24 | 25 | object GraphiteWriter "graphite" { 26 | host = "${CARBON_HOST}" 27 | port = ${CARBON_PORT} 28 | } 29 | 30 | EOF 31 | fi 32 | } 33 | 34 | configure_graphite 35 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/influxdb.sh: -------------------------------------------------------------------------------- 1 | 2 | # configure the InfluxDB Support 3 | # 4 | 5 | if ( [[ -z ${INFLUXDB_HOST} ]] || [[ -z ${INFLUXDB_PORT} ]] ) 6 | then 7 | log_info "no settings for influxdb feature found" 8 | unset INFLUXDB_HOST 9 | unset INFLUXDB_PORT 10 | return 11 | fi 12 | 13 | configure_influxdb() { 14 | 15 | enable_icinga_feature influxdb 16 | 17 | config_file="/etc/icinga2/features-enabled/influxdb.conf" 18 | 19 | # create (overwrite existing) configuration 20 | # 21 | if [[ -e "${config_file}" ]] 22 | then 23 | cat > "${config_file}" <<-EOF 24 | 25 | object InfluxdbWriter "influxdb" { 26 | host = "${INFLUXDB_HOST}" 27 | port = ${INFLUXDB_PORT} 28 | database = "${INFLUXDB_DB}" 29 | username = "${INFLUXDB_USER}" 30 | password = "${INFLUXDB_PASS}" 31 | flush_threshold = 1024 32 | flush_interval = 10s 33 | 34 | host_template = { 35 | measurement = "\$host.check_command$" 36 | tags = { 37 | hostname = "\$host.name$" 38 | } 39 | } 40 | service_template = { 41 | measurement = "\$service.check_command$" 42 | tags = { 43 | hostname = "\$host.name$" 44 | service = "\$service.name$" 45 | } 46 | } 47 | } 48 | 49 | EOF 50 | 51 | fi 52 | } 53 | 54 | configure_influxdb 55 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/msmtp.sh: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | 5 | # a satellite or agent don't need this 6 | # 7 | [[ "${ICINGA2_TYPE}" != "Master" ]] && return 8 | 9 | # configure the ssmtp tool to create notification emails 10 | # 11 | configure_msmtp() { 12 | 13 | file=/etc/msmtprc 14 | 15 | cat << EOF > ${file} 16 | 17 | defaults 18 | tls on 19 | tls_trust_file /etc/ssl/certs/ca-certificates.crt 20 | logfile /var/log/msmtp.log 21 | 22 | account ${ICINGA2_MSMTP_ACC_NAME} 23 | host ${ICINGA2_MSMTP_RELAY_SERVER} 24 | port 587 25 | 26 | 27 | EOF 28 | 29 | if ( [[ ! -z "${ICINGA2_MSMTP_RELAY_USE_STARTTLS}" ]] && [[ "${ICINGA2_MSMTP_RELAY_USE_STARTTLS}" = "true" ]] ) 30 | then 31 | cat << EOF >> ${file} 32 | EOF 33 | fi 34 | 35 | if ( [[ ! -z ${ICINGA2_MSMTP_SMTPAUTH_USER} ]] && [[ ! -z ${ICINGA2_MSMTP_SMTPAUTH_PASS} ]] ) 36 | then 37 | cat << EOF >> ${file} 38 | auth on 39 | user ${ICINGA2_MSMTP_SMTPAUTH_USER} 40 | password ${ICINGA2_MSMTP_SMTPAUTH_PASS} 41 | from ${ICINGA2_MSMTP_REWRITE_DOMAIN} 42 | 43 | account default : ${ICINGA2_MSMTP_ACC_NAME} 44 | EOF 45 | fi 46 | } 47 | 48 | create_smtp_aliases() { 49 | 50 | file=/etc/aliases 51 | 52 | [[ -f ${file} ]] && mv ${file} ${file}-SAVE 53 | 54 | # our default mail-sender 55 | # 56 | cat << EOF > ${file} 57 | root: ${ICINGA2_MSMTP_RECV_ROOT} 58 | EOF 59 | 60 | 61 | if [[ -n "${ICINGA2_MSMTP_ALIASES}" ]] 62 | then 63 | aliases=$(echo ${ICINGA2_MSMTP_ALIASES} | sed -e 's/,/ /g' -e 's/\s+/\n/g' | uniq) 64 | 65 | if [[ ! -z "${aliases}" ]] 66 | then 67 | # add more aliases 68 | # 69 | for u in ${aliases} 70 | do 71 | local=$(echo "${u}" | cut -d: -f1) 72 | email=$(echo "${u}" | cut -d: -f2) 73 | 74 | cat << EOF >> ${file} 75 | ${local}:${email}:${ICINGA2_MSMTP_RELAY_SERVER} 76 | EOF 77 | done 78 | fi 79 | 80 | fi 81 | } 82 | 83 | configure_msmtp 84 | create_smtp_aliases 85 | 86 | # EOF 87 | -------------------------------------------------------------------------------- /rootfs/init/node-wizard_old.expect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect 2 | 3 | # works for 2.9.x 4 | 5 | # exp_internal 1 6 | 7 | log_user 1 8 | set timeout 3 9 | 10 | spawn icinga2 node wizard 11 | 12 | expect -re "Please specify if this is a satellite/client setup" { 13 | send -- "y\r" 14 | } 15 | 16 | expect -re "Please specify the common name " { 17 | send -- "[exec hostname -f]\r" 18 | } 19 | 20 | expect -re "Master/Satellite Common Name" { 21 | send -- "$env(ICINGA2_MASTER)\r" 22 | } 23 | 24 | expect -re "Do you want to establish a connection to the parent node" { 25 | send -- "y\r" 26 | } 27 | 28 | expect -re "endpoint host" { 29 | send -- "$env(ICINGA2_MASTER)\r" 30 | } 31 | 32 | expect -re "endpoint port" { 33 | send -- "5665\r" 34 | } 35 | 36 | expect -re "Add more master/satellite endpoints" { 37 | send -- "n\r" 38 | } 39 | 40 | expect -re "Is this information correct" { 41 | send -- "y\r" 42 | } 43 | 44 | expect -re "Please specify the request ticket generated on your Icinga 2 master" { 45 | send -- "\r" 46 | } 47 | 48 | expect -re "Bind Host" { 49 | send -- "\r" 50 | } 51 | 52 | expect -re "Bind Port" { 53 | send -- "\r" 54 | } 55 | 56 | expect -re "config from parent node" { 57 | send -- "y\r" 58 | } 59 | 60 | expect -re "commands from parent node" { 61 | send -- "y\r" 62 | } 63 | 64 | interact 65 | -------------------------------------------------------------------------------- /rootfs/init/output.sh: -------------------------------------------------------------------------------- 1 | 2 | RED='\033[38;5;202m' 3 | GREEN='\033[38;5;70m' 4 | BLUE='\033[38;5;141m' 5 | WHITE='\033[0;37m' 6 | NC='\033[0m' # No Color 7 | BOLD='\033[1m' 8 | 9 | log_output() { 10 | 11 | level="${1}" 12 | message="${2}" 13 | 14 | if [ -z "${level}" ] 15 | then 16 | printf "$(date +"[%Y-%m-%d %H:%M:%S]") %b\n" "${message}" 17 | else 18 | printf "$(date +"[%Y-%m-%d %H:%M:%S]") %b %b\n" "${level}" "${message}" 19 | fi 20 | } 21 | 22 | log_info() { 23 | message="${1}" 24 | log_output "" "${message}" 25 | } 26 | 27 | log_INFO() { 28 | message="${1}" 29 | log_output "" "${BOLD}${message}${NC}" 30 | } 31 | 32 | log_warn() { 33 | message="${1}" 34 | log_output "${BLUE}${BOLD}WARNING${NC}" "${message}" 35 | } 36 | 37 | log_WARN() { 38 | message="${1}" 39 | log_output "${RED}${BOLD}WARNING${NC}" "${RED}${BOLD}${message}${NC}" 40 | } 41 | 42 | log_error() { 43 | message="${1}" 44 | log_output "${RED}${BOLD}ERROR${NC}" "${message}" 45 | } 46 | 47 | log_debug() { 48 | message="${1}" 49 | log_output "${BOLD}DEBUG${NC}" "${message}" 50 | } 51 | -------------------------------------------------------------------------------- /rootfs/init/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | set +e 6 | set +u 7 | 8 | 9 | finish() { 10 | rv=$? 11 | log_INFO "exit with signal '${rv}'" 12 | 13 | if [[ ${rv} -gt 0 ]] 14 | then 15 | sleep 4s 16 | fi 17 | 18 | if [[ "${DEBUG}" = "true" ]] 19 | then 20 | caller 21 | fi 22 | 23 | log_info "" 24 | 25 | exit ${rv} 26 | } 27 | 28 | trap finish SIGINT SIGTERM INT TERM EXIT 29 | 30 | # ------------------------------------------------------------------------------------------------- 31 | 32 | . /etc/profile 33 | 34 | . /init/output.sh 35 | . /usr/bin/vercomp 36 | . /init/environment.sh 37 | 38 | #env | sort 39 | #sleep 5s 40 | 41 | # ------------------------------------------------------------------------------------------------- 42 | 43 | ICINGA2_PARAMS= 44 | 45 | # if [[ -z ${DEBUG+x} ]]; then echo "DEBUG is unset"; else echo "DEBUG is set to '$DEBUG'"; fi 46 | 47 | if [[ ! -z ${DEBUG+x} ]] 48 | then 49 | # env | grep DEBUG 50 | if ( [[ "${DEBUG}" = true ]] || [[ "${DEBUG}" = "true" ]] || [[ ${DEBUG} -eq 1 ]] ) 51 | then 52 | export DEBUG="true" 53 | else 54 | unset DEBUG 55 | fi 56 | fi 57 | 58 | ICINGA2_PARAMS="--log-level ${ICINGA2_LOGLEVEL}" 59 | 60 | # ------------------------------------------------------------------------------------------------- 61 | 62 | # side channel to inject some wild-style customized scripts 63 | # THIS CAN BREAK THE COMPLETE ICINGA2 CONFIGURATION! 64 | # 65 | custom_scripts() { 66 | 67 | if [[ -d /init/custom.d ]] 68 | then 69 | for f in /init/custom.d/* 70 | do 71 | case "$f" in 72 | *.sh) 73 | log_WARN "------------------------------------------------------" 74 | log_WARN "RUN SCRIPT: ${f}" 75 | log_WARN "YOU SHOULD KNOW WHAT YOU'RE DOING." 76 | log_WARN "THIS CAN BREAK THE COMPLETE ICINGA2 CONFIGURATION!" 77 | nohup "${f}" > /dev/stdout 2>&1 & 78 | log_WARN "------------------------------------------------------" 79 | ;; 80 | *) 81 | log_warn "ignoring file ${f}" 82 | ;; 83 | esac 84 | echo 85 | done 86 | fi 87 | } 88 | 89 | 90 | configure_modules() { 91 | 92 | log_info "configure modules" 93 | 94 | if [[ -d /init/modules.d ]] 95 | then 96 | for f in /init/modules.d/* 97 | do 98 | case "$f" in 99 | *.sh) 100 | log_info " $(basename ${f} .sh)" 101 | . ${f} 102 | ;; 103 | *) 104 | # log_warn "ignoring file ${f}" 105 | ;; 106 | esac 107 | done 108 | fi 109 | } 110 | 111 | 112 | start_icinga2_cert_service() { 113 | 114 | if [[ ! -f /usr/local/icinga2-cert-service/bin/icinga2-cert-service.rb ]] 115 | then 116 | return 117 | fi 118 | 119 | nohup /usr/local/icinga2-cert-service/bin/icinga2-cert-service.rb & # > /dev/stdout 2>&1 & 120 | } 121 | 122 | 123 | start_runtime_script() { 124 | 125 | local script="/init/runtime/${1}" 126 | 127 | if [ -f "${script}" ] 128 | then 129 | nohup "${script}" > /dev/stdout 2>&1 & 130 | else 131 | log_WARN "unknown runtime script: '${1}'" 132 | fi 133 | } 134 | 135 | 136 | run() { 137 | 138 | log_info "" 139 | log_info "prepare system" 140 | 141 | . /init/common.sh 142 | 143 | prepare 144 | 145 | fix_sys_caps 146 | 147 | if [[ ! -z ${DEVELOPMENT_MODUS+x} ]] && [[ ${DEVELOPMENT_MODUS} = true ]] || [[ ${DEVELOPMENT_MODUS} -eq 1 ]] 148 | then 149 | log_debug "DEVELOPMENT_MODUS is activ" 150 | 151 | tail -f /dev/null 152 | fi 153 | 154 | validate_certservice_environment 155 | 156 | version_of_icinga_master 157 | 158 | # create and configure database 159 | # 160 | [[ "${ICINGA2_TYPE}" = "Master" ]] && . /init/database/mysql.sh 161 | 162 | . /init/configure_icinga.sh 163 | . /init/api_user.sh 164 | 165 | # modules 166 | # 167 | [[ "${ICINGA2_TYPE}" = "Master" ]] && configure_modules 168 | 169 | correct_rights 170 | 171 | log_info "----------------------------------------------------" 172 | log_info " Icinga ${ICINGA2_TYPE} Version ${ICINGA2_VERSION} - build: ${BUILD_DATE}" 173 | log_info "----------------------------------------------------" 174 | 175 | custom_scripts 176 | 177 | if [[ "${ICINGA2_TYPE}" = "Master" ]] 178 | then 179 | # backup the generated zones 180 | # 181 | start_runtime_script inotify.sh 182 | start_icinga2_cert_service 183 | start_runtime_script watch_satellites.sh 184 | else 185 | start_runtime_script ca_validator.sh 186 | if [[ ! -e /tmp/final ]] 187 | then 188 | start_runtime_script zone_watcher.sh 189 | fi 190 | fi 191 | 192 | log_info "start init process ..." 193 | 194 | /usr/sbin/icinga2 \ 195 | daemon \ 196 | ${ICINGA2_PARAMS} 197 | } 198 | 199 | run 200 | 201 | # EOF 202 | -------------------------------------------------------------------------------- /rootfs/init/runtime/ca_validator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # periodic check of the (satellite) CA file 4 | # **this use the API from the icinga-cert-service!** 5 | # 6 | # when the CA file are not in sync, we restart the container to 7 | # getting a new certificate 8 | # 9 | # BE CAREFUL WITH THIS 'FEATURE'! 10 | # IT'S JUST A FIX FOR A FAULTY USE. 11 | # 12 | 13 | . /init/output.sh 14 | . /init/environment.sh 15 | 16 | . /init/cert/certificate_handler.sh 17 | 18 | log_info "start the CA validator for '${HOSTNAME}'" 19 | 20 | while true 21 | do 22 | # check the creation date of our certificate request against the 23 | # connected endpoints 24 | # (take a look in the test.sh line 112:125) 25 | # 26 | sign_file="${ICINGA2_LIB_DIRECTORY}/backup/sign_${HOSTNAME}.json" 27 | 28 | if [[ -f ${sign_file} ]] 29 | then 30 | ICINGA2_API_PORT=${ICINGA2_API_PORT:-5665} 31 | warn=300 # 5 minuten 32 | crit=600 # 10 minuten 33 | 34 | message=$(jq --raw-output .message ${sign_file} 2> /dev/null) 35 | master_name=$(jq --raw-output .master_name ${sign_file} 2> /dev/null) 36 | master_ip=$(jq --raw-output .master_ip ${sign_file} 2> /dev/null) 37 | date=$(jq --raw-output .date ${sign_file} 2> /dev/null) 38 | timestamp=$(jq --raw-output .timestamp ${sign_file} 2> /dev/null) 39 | checksum=$(jq --raw-output .checksum ${sign_file} 2> /dev/null) 40 | 41 | # timestamp must be in UTC! 42 | current_timestamp=$(date +%s) 43 | diff=$(( ${current_timestamp} - ${timestamp} )) 44 | diff_full=$(printf '%dh:%dm:%ds\n' $((${diff}/3600)) $((${diff}%3600/60)) $((${diff}%60))) 45 | 46 | curl_opts= 47 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem ]] 48 | then 49 | curl_opts="${curl_opts} --capath ${ICINGA2_CERT_DIRECTORY}" 50 | curl_opts="${curl_opts} --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem" 51 | curl_opts="${curl_opts} --cacert ${ICINGA2_CERT_DIRECTORY}/ca.crt" 52 | else 53 | curl_opts="--insecure" 54 | fi 55 | 56 | code=$(curl \ 57 | --user ${CERT_SERVICE_API_USER}:${CERT_SERVICE_API_PASSWORD} \ 58 | --silent \ 59 | ${curl_opts} \ 60 | --header 'Accept: application/json' \ 61 | https://${ICINGA2_MASTER}:${ICINGA2_API_PORT}/v1/status/ApiListener) 62 | 63 | result=${?} 64 | 65 | if [[ ${result} -eq 0 ]] 66 | then 67 | connected=$(echo "${code}" | jq --raw-output '.results[].status.api.conn_endpoints | join(",")' | grep -c ${HOSTNAME}) 68 | 69 | if [[ ${connected} -eq 1 ]] 70 | then 71 | log_info "We are connected to our Master since ${diff_full} \m/" 72 | elif [[ ${connected} -eq 0 ]] 73 | then 74 | 75 | num_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_endpoints") 76 | num_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_conn_endpoints") 77 | num_not_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_not_conn_endpoints") 78 | conn_endpoints=$(echo "${code}" | jq --raw-output '.results[].status.api.conn_endpoints | join(",")') 79 | not_conn_endpoints=$(echo "${code}" | jq --raw-output '.results[].status.api.not_conn_endpoints | join(",")') 80 | 81 | if [[ "${DEBUG}" = "true" ]] 82 | then 83 | log_debug "endpoints summary:" 84 | log_debug "totaly: '${num_endpoints}' / connected: '${num_conn_endpoints}' / not connected: '${num_not_conn_endpoints}'" 85 | log_debug "i'm connected: ${connected}" 86 | log_debug "" 87 | log_debug "connected endpoints: " 88 | log_debug "${conn_endpoints}" 89 | log_debug "" 90 | log_debug "not connected endpoints: " 91 | log_debug "${not_conn_endpoints}" 92 | log_debug "" 93 | log_debug "diff: '${diff}' | warn: '${warn}' / crit: '${crit}'" 94 | log_debug "" 95 | fi 96 | 97 | if [[ ${checksum} != null ]] 98 | then 99 | if [[ ${diff} -gt ${warn} ]] && [[ ${diff} -lt ${crit} ]] 100 | then 101 | log_warn "Our certificate request is already ${diff_full} old" 102 | log_warn "and we're not connected to the master yet." 103 | log_warn "This may be a major problem" 104 | log_warn "If this problem persists, the satellite will be reset and restarted." 105 | 106 | elif [[ ${diff} -gt ${crit} ]] 107 | then 108 | log_error "Our certificate request is already ${diff_full} old" 109 | log_error "and we're not connected to the master yet." 110 | log_error "That's a problem" 111 | log_INFO "This satellite will now be reset and restarted" 112 | 113 | pid=$(ps ax | grep icinga2 | grep -v grep | grep daemon | awk '{print $1}') 114 | [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] && killall --verbose --signal HUP icinga2 > /dev/null 2> /dev/null 115 | 116 | exit 1 117 | fi 118 | fi 119 | else 120 | # DAS GEHT? 121 | : 122 | fi 123 | fi 124 | else 125 | log_error "i can't find the sign file '${sign_file}'" 126 | log_error "That's a problem" 127 | log_INFO "This satellite will now be reset and restarted" 128 | 129 | pid=$(ps ax | grep icinga2 | grep -v grep | grep daemon | awk '{print $1}') 130 | [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] && killall --verbose --signal HUP icinga2 > /dev/null 2> /dev/null 131 | 132 | exit 1 133 | fi 134 | 135 | validate_local_ca 136 | 137 | if [[ ! -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.key ]] 138 | then 139 | log_error "The validation of our CA was not successful." 140 | log_error "That's a problem" 141 | log_INFO "This satellite will now be reset and restarted" 142 | 143 | rm -rf ${ICINGA2_CERT_DIRECTORY}/* 144 | 145 | pid=$(ps ax | grep icinga2 | grep -v grep | grep daemon | awk '{print $1}') 146 | [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] && killall --verbose --signal HUP icinga2 > /dev/null 2> /dev/null 147 | 148 | exit 1 149 | fi 150 | 151 | sleep 5m 152 | done 153 | -------------------------------------------------------------------------------- /rootfs/init/runtime/inotify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use inotify to detect changes in the ${monitored_directory} and sync 4 | # changes to ${backup_directory} 5 | # when a 'delete' event is triggerd, the file/directory will also removed 6 | # from ${backup_directory} 7 | # 8 | # in this case, we need only a sync of all 'zones.*' files/directory 9 | # 10 | 11 | . /init/output.sh 12 | 13 | monitored_directory="/etc/icinga2" 14 | backup_directory="/var/lib/icinga2/backup" 15 | 16 | log_info "start the service zone monitor" 17 | 18 | inotifywait \ 19 | --monitor \ 20 | --recursive \ 21 | --event create \ 22 | --event attrib \ 23 | --event close_write \ 24 | --event delete \ 25 | ${monitored_directory} | 26 | while read path action file 27 | do 28 | 29 | if ( [[ -z "${file}" ]] || [[ ! ${file} =~ ^zones* ]] ) 30 | then 31 | continue 32 | fi 33 | 34 | [[ "${DEBUG}" = "true" ]] && log_debug "service zone monitor - The file '$file' appeared in directory '$path' via '$action'" 35 | 36 | # monitor DELETE 37 | # 38 | if [[ "${action}" = "DELETE" ]] 39 | then 40 | # remove file 41 | # 42 | rm -f ${backup_directory}/$(basename ${path})/${file} 43 | 44 | # monitor DELETE,ISDIR 45 | # 46 | elif [[ "${action}" = "DELETE,ISDIR" ]] 47 | then 48 | # remove directory 49 | # 50 | rm -rf ${backup_directory}/${file} 51 | fi 52 | done 53 | -------------------------------------------------------------------------------- /rootfs/init/runtime/service_handler.sh: -------------------------------------------------------------------------------- 1 | 2 | start_icinga() { 3 | 4 | exec /usr/sbin/icinga2 \ 5 | daemon \ 6 | --log-level debug 7 | } 8 | 9 | 10 | kill_icinga() { 11 | log_warn "headshot ..." 12 | pid=$(ps ax | grep icinga2 | grep -v grep | grep daemon | awk '{print $1}') 13 | [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] && killall --verbose --signal HUP icinga2 > /dev/null 2> /dev/null 14 | } 15 | -------------------------------------------------------------------------------- /rootfs/init/runtime/watch_satellites.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use inotify to detect changes in the ${monitored_directory} and sync 4 | # changes to ${backup_directory} 5 | # when a 'delete' event is triggerd, the file/directory will also removed 6 | # from ${backup_directory} 7 | # 8 | # in this case, we need only a sync of all 'zones.*' files/directory 9 | # 10 | 11 | . /init/output.sh 12 | . /init/environment.sh 13 | 14 | log_info "start the satellite monitor" 15 | 16 | 17 | while true 18 | do 19 | curl_opts= 20 | if [[ -f ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem ]] 21 | then 22 | curl_opts="${curl_opts} --capath ${ICINGA2_CERT_DIRECTORY}" 23 | curl_opts="${curl_opts} --cert ${ICINGA2_CERT_DIRECTORY}/${HOSTNAME}.pem" 24 | curl_opts="${curl_opts} --cacert ${ICINGA2_CERT_DIRECTORY}/ca.crt" 25 | else 26 | curl_opts="--insecure" 27 | fi 28 | 29 | code=$(curl \ 30 | --user "${CERT_SERVICE_API_USER}:${CERT_SERVICE_API_PASSWORD}" \ 31 | --silent \ 32 | "${curl_opts}" \ 33 | --header 'Accept: application/json' \ 34 | "https://localhost:5665/v1/status/ApiListener") 35 | 36 | result=${?} 37 | 38 | if [[ ${result} -eq 0 ]] 39 | then 40 | num_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_endpoints") 41 | num_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_conn_endpoints") 42 | num_not_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_not_conn_endpoints") 43 | conn_endpoints=$(echo "${code}" | jq --raw-output '.results[].status.api.conn_endpoints | join(",")') 44 | not_conn_endpoints=$(echo "${code}" | jq --raw-output '.results[].status.api.not_conn_endpoints | join(",")') 45 | 46 | #log_debug "endpoints summary:" 47 | log_info "totaly endpoints: '${num_endpoints}' / connected: '${num_conn_endpoints}' / not connected: '${num_not_conn_endpoints}'" 48 | log_info "connected endpoints: " 49 | log_info " ${conn_endpoints}" 50 | log_info "not connected endpoints: " 51 | log_info " ${not_conn_endpoints}" 52 | fi 53 | 54 | 55 | 56 | sleep 10m 57 | done 58 | -------------------------------------------------------------------------------- /rootfs/init/runtime/zone_debugger.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use inotify to detect changes in the ${monitored_directory} and sync 4 | # changes to ${backup_directory} 5 | # when a 'delete' event is triggerd, the file/directory will also removed 6 | # from ${backup_directory} 7 | # 8 | # in this case, we need only a sync of all 'zones.*' files/directory 9 | # 10 | 11 | . /init/output.sh 12 | 13 | monitored_directory="/var/lib/icinga2" 14 | hostname_f=$(hostname -f) 15 | 16 | log_info "start the api zone debugger" 17 | 18 | 19 | grep -nrB2 "template Host" ${monitored_directory}/* 20 | 21 | inotifywait \ 22 | --monitor \ 23 | --recursive \ 24 | --event create \ 25 | --event delete \ 26 | --event attrib \ 27 | --event close_write \ 28 | --event moved_to \ 29 | --event moved_from \ 30 | ${monitored_directory} | 31 | while read path action file 32 | do 33 | [[ -z "${file}" ]] && continue 34 | #[[ ${path} =~ backup ]] && continue 35 | 36 | if [[ "${file}" == "current" ]] || [[ "${file}" == "_etc" ]] || [[ "${file}" == ".timestamp" ]] 37 | then 38 | continue 39 | fi 40 | 41 | if [[ "${DEBUG}" = "true" ]] 42 | then 43 | log_debug "api zone debugger - The file '$file' appeared in directory '$path' via '$action'" 44 | fi 45 | 46 | done 47 | -------------------------------------------------------------------------------- /rootfs/init/runtime/zone_watcher.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use inotify to detect changes in the ${monitored_directory} and sync 4 | # changes to ${backup_directory} 5 | # when a 'delete' event is triggerd, the file/directory will also removed 6 | # from ${backup_directory} 7 | # 8 | # in this case, we need only a sync of all 'zones.*' files/directory 9 | # 10 | 11 | . /init/output.sh 12 | 13 | monitored_directory="/var/lib/icinga2" 14 | hostname_f=$(hostname -f) 15 | 16 | attrib="false" 17 | 18 | log_info "start the api zone monitor" 19 | 20 | inotifywait \ 21 | --monitor \ 22 | --recursive \ 23 | --event create \ 24 | --event attrib \ 25 | --event close_write \ 26 | ${monitored_directory} | 27 | while read path action file 28 | do 29 | [[ -z "${file}" ]] && continue 30 | [[ ${path} =~ backup ]] && continue 31 | 32 | if [[ "${file}" == "current" ]] || [[ "${file}" == "_etc" ]] || [[ "${file}" == ".timestamp" ]] 33 | then 34 | continue 35 | fi 36 | 37 | [[ "${DEBUG}" = "true" ]] && log_debug "api zone monitor - The file '$file' appeared in directory '$path' via '$action'" 38 | 39 | if [[ "${action}" = "ATTRIB" ]] 40 | then 41 | attrib="true" 42 | fi 43 | 44 | # if [[ "${DEBUG}" = "true" ]] 45 | # then 46 | # log_debug "api zone monitor - attrib: '${attrib}'" 47 | # log_debug "api zone monitor - action: '${action}'" 48 | # fi 49 | 50 | # monitor CLOSE_WRITE,CLOSE 51 | # 52 | if [[ "${attrib}" = "true" ]] && [[ "${action}" = "CLOSE_WRITE,CLOSE" ]] 53 | then 54 | ## only for the ${HOSTNAME}.crt 55 | ## 56 | #if [[ ${file} =~ ${hostname_f}.crt ]] 57 | #then 58 | # log_info "our certificate are replicated." 59 | # log_info "replace the static zone config (if needed)" 60 | # 61 | # sed -i \ 62 | # -e 's|^object Zone ZoneName.*}$|object Zone ZoneName { endpoints = [ NodeName ]; parent = "master" }|g' \ 63 | # /etc/icinga2/zones.conf 64 | # 65 | # cp /etc/icinga2/zones.conf ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf 66 | #fi 67 | 68 | attrib="false" 69 | 70 | # monitor CREATE,ISDIR 71 | # 72 | elif [[ "${action}" = "CREATE,ISDIR" ]] 73 | then 74 | # only if the directory is equal to the ${HOSTNAME} 75 | # 76 | if [[ ${file} =~ ${hostname_f} ]] 77 | then 78 | log_info "the zone configuration for myself has changed." 79 | log_info "we must remove the old endpoint configuration from the static zones.conf" 80 | 81 | sed -i \ 82 | -e "s/^\(object\ Endpoint\ NodeName .*\)/\/\/ \1/" \ 83 | /etc/icinga2/zones.conf 84 | 85 | cp /etc/icinga2/zones.conf ${ICINGA2_LIB_DIRECTORY}/backup/zones.conf 86 | 87 | if [[ -d /etc/icinga2/zones.d/global-templates ]] 88 | then 89 | log_info "we remove also the static global-templates directory" 90 | rm -rf /etc/icinga2/zones.d/global-templates 91 | fi 92 | 93 | if [[ -d /etc/icinga2/zones.d/director-global ]] 94 | then 95 | log_info "we remove also the static director-global directory" 96 | rm -rf /etc/icinga2/zones.d/director-global 97 | fi 98 | 99 | # touch file for later add the satellite to the master over API 100 | # 101 | touch /tmp/add_host 102 | 103 | log_INFO "now, we restart ourself for certificate and zone reloading." 104 | 105 | # kill myself to finalize 106 | # 107 | pid=$(ps ax -o pid,args | grep -v grep | grep icinga2 | grep daemon | awk '{print $1}') 108 | if [[ $(echo -e "${pid}" | wc -w) -gt 0 ]] 109 | then 110 | [[ "${DEBUG}" = "true" ]] && log_debug " killall --verbose --signal HUP icinga2" 111 | killall --verbose --signal HUP icinga2 > /dev/null 2> /dev/null 112 | fi 113 | fi 114 | 115 | attrib="false" 116 | fi 117 | done 118 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/cert_service.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for the Certificate Service 3 | # 4 | wait_for_icinga_cert_service() { 5 | 6 | # the CERT-Service API use an Basic-Auth as first Authentication *AND* 7 | # use an own API Userr 8 | if [[ "${USE_CERT_SERVICE}" = "true" ]] 9 | then 10 | 11 | # use the new Cert Service to create and get a valide certificat for distributed icinga services 12 | # 13 | if ( 14 | [[ ! -z ${CERT_SERVICE_BA_USER} ]] && 15 | [[ ! -z ${CERT_SERVICE_BA_PASSWORD} ]] && 16 | [[ ! -z ${CERT_SERVICE_API_USER} ]] && 17 | [[ ! -z ${CERT_SERVICE_API_PASSWORD} ]] 18 | ) 19 | then 20 | 21 | . /init/wait_for/dns.sh 22 | . /init/wait_for/port.sh 23 | 24 | wait_for_dns ${CERT_SERVICE_SERVER} 25 | wait_for_port ${CERT_SERVICE_SERVER} ${CERT_SERVICE_PORT} 50 26 | 27 | # okay, the web service is available 28 | # but, we have a problem, when he runs behind a proxy ... 29 | # eg.: https://monitoring-proxy.tld/cert-cert-service 30 | # 31 | RETRY=30 32 | # wait for the cert-service health check behind a proxy 33 | # 34 | until [[ ${RETRY} -le 0 ]] 35 | do 36 | 37 | health=$(curl \ 38 | --silent \ 39 | --location \ 40 | --insecure \ 41 | --write-out "%{http_code}\n" \ 42 | ${CERT_SERVICE_PROTOCOL}://${CERT_SERVICE_SERVER}:${CERT_SERVICE_PORT}${CERT_SERVICE_PATH}v2/health-check) 43 | 44 | if ( [[ $? -eq 0 ]] && [[ "${health}" == "healthy200" ]] ) 45 | then 46 | break 47 | fi 48 | 49 | health= 50 | 51 | log_info "wait for the health check for the certificate service on '${CERT_SERVICE_SERVER}'" 52 | sleep 5s 53 | RETRY=$(expr ${RETRY} - 1) 54 | done 55 | 56 | if [[ ${RETRY} -le 0 ]] 57 | then 58 | log_error "The certificate service '${CERT_SERVICE_SERVER}' could not be reached" 59 | exit 1 60 | fi 61 | 62 | sleep 5s 63 | fi 64 | else 65 | log_warn "missing variables:" 66 | log_warn " CERT_SERVICE_BA_USER: '${CERT_SERVICE_BA_USER}'" 67 | log_warn " CERT_SERVICE_BA_PASSWORD: '${CERT_SERVICE_BA_PASSWORD}'" 68 | log_warn " CERT_SERVICE_API_USER: '${CERT_SERVICE_API_USER}'" 69 | log_warn " CERT_SERVICE_API_PASSWORD: '${CERT_SERVICE_API_PASSWORD}'" 70 | fi 71 | } 72 | 73 | wait_for_icinga_cert_service 74 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/dns.sh: -------------------------------------------------------------------------------- 1 | 2 | wait_for_dns() { 3 | 4 | local server=${1} 5 | local max_retry=${2:-9} 6 | local silent=${3:-} 7 | 8 | local retry=0 9 | local host= 10 | 11 | if [[ -z ${silent} ]] || [[ "${silent}" = "" ]] 12 | then 13 | silent="" 14 | elif [[ ! -z ${silent} ]] || [[ "${silent}" = "silent" ]] 15 | then 16 | silent="silent" 17 | fi 18 | 19 | #[[ -z "${silent}" ]] && log_info "check if a DNS record for '${server}' is available" 20 | 21 | until ( [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] ) 22 | do 23 | # icinga2-master.matrix.lan has address 172.23.0.3 24 | # Host icinga2-master-fail not found: 3(NXDOMAIN) 25 | host=$(host ${server} 2> /dev/null) 26 | 27 | if [[ -z "${host}" ]] || [[ $(echo -e "${host}" | grep -c "has address") -eq 0 ]] 28 | then 29 | retry=$(expr ${retry} + 1) 30 | #[[ -z "${silent}" ]] && log_info " wait for a valid dns record (${retry}/${max_retry})" 31 | sleep 10s 32 | else 33 | break 34 | fi 35 | done 36 | 37 | if [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] 38 | then 39 | log_error "a DNS record for '${server}' could not be determined." 40 | log_error "$(host ${server})" 41 | exit 1 42 | fi 43 | } 44 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/icinga_master.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for the Icinga2 Master 3 | # 4 | wait_for_icinga_master() { 5 | 6 | # I can't wait for myself. 7 | # 8 | [[ "${ICINGA2_TYPE}" = "Master" ]] && return 9 | 10 | . /init/wait_for/dns.sh 11 | . /init/wait_for/port.sh 12 | 13 | wait_for_dns ${ICINGA2_MASTER} 14 | wait_for_port ${ICINGA2_MASTER} 5665 50 15 | 16 | # log_info "Waiting for icinga2 master on host '${ICINGA2_MASTER}' to come up" 17 | 18 | sleep 5s 19 | } 20 | 21 | wait_for_icinga_master 22 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/mysql.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for mariadb / mysql 3 | # 4 | wait_for_database() { 5 | 6 | . /init/wait_for/dns.sh 7 | . /init/wait_for/port.sh 8 | 9 | wait_for_dns ${MYSQL_HOST} 10 | wait_for_port ${MYSQL_HOST} ${MYSQL_PORT} 15 11 | 12 | sleep 2s 13 | 14 | RETRY=10 15 | 16 | # must start initdb and do other jobs well 17 | # 18 | until [[ ${RETRY} -le 0 ]] 19 | do 20 | mysql ${MYSQL_OPTS} --execute="select 1 from mysql.user limit 1" > /dev/null 21 | 22 | [[ $? -eq 0 ]] && break 23 | 24 | log_info "wait for the database for her initdb and all other jobs" 25 | sleep 13s 26 | RETRY=$(expr ${RETRY} - 1) 27 | done 28 | 29 | sleep 2s 30 | } 31 | 32 | wait_for_database 33 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/port.sh: -------------------------------------------------------------------------------- 1 | 2 | wait_for_port() { 3 | 4 | local server=${1} 5 | local port=${2} 6 | local max_retry=${3:-30} 7 | local silent=${4:-} 8 | 9 | local retry=0 10 | local sleep=10 11 | 12 | if [[ -z ${silent} ]] || [[ "${silent}" = "" ]] 13 | then 14 | silent="" 15 | elif [[ ! -z ${silent} ]] || [[ "${silent}" = "silent" ]] 16 | then 17 | silent="silent" 18 | fi 19 | 20 | #[[ -z "${silent}" ]] && log_info "check if the port ${port} for '${server}' is available" 21 | 22 | until [[ ${max_retry} -lt ${retry} ]] 23 | do 24 | # -v Verbose 25 | # -w secs Timeout for connects and final net reads 26 | # -X proto Proxy protocol: "4", "5" (SOCKS) or "connect" 27 | # 28 | status=$(nc -v -w1 -X connect ${server} ${port} 2>&1 > /dev/null) 29 | 30 | #log_debug "'${status}'" 31 | 32 | if [[ $(echo "${status}" | grep -c succeeded) -eq 1 ]] 33 | then 34 | break 35 | else 36 | retry=$(expr ${retry} + 1) 37 | #[[ -z "${silent}" ]] && log_info " wait for an open port (${retry}/${max_retry})" 38 | sleep ${sleep}s 39 | fi 40 | done 41 | 42 | if [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] 43 | then 44 | log_error "could not connect to instance '${server}'" 45 | exit 1 46 | fi 47 | } 48 | 49 | -------------------------------------------------------------------------------- /rootfs/usr/bin/vercomp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash 4 | vercomp() { 5 | 6 | [[ $1 == $2 ]] && return 0 7 | 8 | local IFS=. 9 | local i ver1=($1) ver2=($2) 10 | # fill empty fields in ver1 with zeros 11 | for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 12 | do 13 | ver1[i]=0 14 | done 15 | 16 | for ((i=0; i<${#ver1[@]}; i++)) 17 | do 18 | if [[ -z ${ver2[i]} ]] 19 | then 20 | # fill empty fields in ver2 with zeros 21 | ver2[i]=0 22 | fi 23 | if ((10#${ver1[i]} > 10#${ver2[i]})) 24 | then 25 | return 1 26 | fi 27 | if ((10#${ver1[i]} < 10#${ver2[i]})) 28 | then 29 | return 2 30 | fi 31 | done 32 | return 0 33 | } 34 | 35 | testvercomp () { 36 | vercomp $1 $2 37 | case $? in 38 | 0) op='=';; 39 | 1) op='>';; 40 | 2) op='<';; 41 | esac 42 | if [[ $op != $3 ]] 43 | then 44 | echo "FAIL: Expected '$3', Actual '$op', Arg1 '$1', Arg2 '$2'" 45 | else 46 | echo "Pass: '$1 $op $2'" 47 | fi 48 | } -------------------------------------------------------------------------------- /rootfs/usr/lib/monitoring-plugins/check_hostname: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # dummy check host check 4 | 5 | echo -e "$(date +"%Y-%m-%d %H:%M:%S") $(hostname -f)" 6 | 7 | exit 0 8 | -------------------------------------------------------------------------------- /rootfs/usr/lib/monitoring-plugins/check_procs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # dummy check for alpine 4 | 5 | exit 0 6 | -------------------------------------------------------------------------------- /rootfs/usr/lib/monitoring-plugins/check_xping: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # ---------------------------------------------------------------------------------------- 4 | 5 | STATE_OK=0 6 | STATE_WARNING=1 7 | STATE_CRITICAL=2 8 | STATE_UNKNOWN=3 9 | STATE_DEPENDENT=4 10 | 11 | # ---------------------------------------------------------------------------------------- 12 | 13 | # Parse parameters 14 | while [ $# -gt 0 ] 15 | do 16 | case "${1}" in 17 | -H|--host) shift 18 | HOST="${1}" ;; 19 | esac 20 | shift 21 | done 22 | 23 | [ -z $WRTA ] && WRTA=100 24 | [ -z $CRTA ] && CRTA=200 25 | [ -z $WPL ] && WPL=5 26 | [ -z $CPL ] && CPL=2 27 | 28 | PING_RESPONSE=$( (/usr/sbin/fping --ipv4 --count=2 --elapsed --unreach --name --stats "$HOST") 2>&1) 29 | 30 | ALIVE=$(echo -e "${PING_RESPONSE}" | grep "alive" | awk '{print $1}') 31 | UNREACHABLE=$(echo -e "${PING_RESPONSE}" | grep "unreachable" | awk '{print $1}') 32 | RTA_MIN=$(echo -e "${PING_RESPONSE}" | grep "min round trip time" | awk '{print $1}') 33 | RTA_AVG=$(echo -e "${PING_RESPONSE}" | grep "avg round trip time" | awk '{print $1}') 34 | RTA_MAX=$(echo -e "${PING_RESPONSE}" | grep "max round trip time" | awk '{print $1}') 35 | 36 | if [ ${ALIVE} -eq 1 ] 37 | then 38 | echo "PING OK - Packet loss = 0%, RTA = ${RTA_AVG} ms | rta_min=${RTA_MIN} rta_avg=${RTA_AVG} rta_max=${RTA_MAX}" 39 | exit ${STATE_OK} 40 | fi 41 | 42 | if [ ${UNREACHABLE} -eq 1 ] 43 | then 44 | echo "PING CRITICAL - Host unreachable" 45 | exit ${STATE_CRITICAL} 46 | fi 47 | 48 | exit $? 49 | -------------------------------------------------------------------------------- /tests/integration_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ICINGA2_MASTER=${ICINGA2_MASTER:-"localhost"} 4 | ICINGA2_API_PORT=${ICINGA2_API_PORT:-5665} 5 | ICINGA2_API_USER="root" 6 | ICINGA2_API_PASSWORD="icinga" 7 | 8 | ICINGA2_UPTIME=125 9 | 10 | CERTIFICATE_SERVER=${CERTIFICATE_SERVER:-${ICINGA2_MASTER}} 11 | CERTIFICATE_PORT=${CERTIFICATE_PORT:-443} 12 | CERTIFICATE_PATH=${CERTIFICATE_PATH:-/cert-service/} 13 | 14 | [[ ${CERTIFICATE_PORT} = *443 ]] && protocol=https || protocol=http 15 | export CERT_SERVICE_PROTOCOL=${protocol} 16 | 17 | CURL=$(which curl 2> /dev/null) 18 | 19 | # wait for the Icinga2 Instances Master or Satellite 20 | # 21 | wait_for_icinga_instances() { 22 | 23 | echo "wait for the icinga2 instances" 24 | 25 | for s in $(docker-compose ps | grep icinga2 | awk '{print($1)}') 26 | do 27 | instance_uptime= 28 | 29 | if [ $(echo "${s}" | egrep -ce satellite) -eq 1 ] 30 | then 31 | # satellite 32 | instance_uptime=30 33 | echo "an satellite instance should run ${instance_uptime} seconds without interruption" 34 | else 35 | # master 36 | instance_uptime=100 37 | echo "the master instance must run ${instance_uptime} seconds without interruption" 38 | fi 39 | 40 | backend_network=$(docker network ls | egrep "*icinga2_backend*" | awk '{print $2}') 41 | 42 | ip=$(docker network inspect ${backend_network} | jq -r ".[].Containers | to_entries[] | select(.value.Name==\"${s}\").value.IPv4Address" | awk -F "/" '{print $1}') 43 | 44 | echo " ${s} - ${ip}" 45 | 46 | RETRY=35 47 | 48 | until [[ ${RETRY} -le 0 ]] 49 | do 50 | 51 | echo " ${s} | ${RETRY}" 52 | 53 | code=$(curl \ 54 | --user ${ICINGA2_API_USER}:${ICINGA2_API_PASSWORD} \ 55 | --silent \ 56 | --insecure \ 57 | --header 'Accept: application/json' \ 58 | https://${ip}:${ICINGA2_API_PORT}/v1/status/CIB) 59 | 60 | if [[ ! -z "${code}" ]] 61 | then 62 | uptime=$(echo "${code}" | jq --raw-output '.results[].status.uptime' 2> /dev/null) 63 | 64 | utime=${uptime%.*} 65 | 66 | echo " - ${utime} / ${instance_uptime}" 67 | 68 | if [[ ${utime} -gt ${instance_uptime} ]] 69 | then 70 | echo "the icinga2 instance ${s} is ${utime} seconds up and alive" 71 | break 72 | else 73 | sleep 10s 74 | RETRY=$(expr ${RETRY} - 1) 75 | fi 76 | else 77 | sleep 10s 78 | RETRY=$(expr ${RETRY} - 1) 79 | fi 80 | done 81 | 82 | done 83 | } 84 | 85 | 86 | # wait for the Certificate Service 87 | # 88 | wait_for_icinga_cert_service() { 89 | 90 | echo -e "\nwait for the certificate service" 91 | 92 | RETRY=35 93 | # wait for the running certificate service 94 | # 95 | until [[ ${RETRY} -le 0 ]] 96 | do 97 | timeout 1 bash -c "cat < /dev/null > /dev/tcp/${CERTIFICATE_SERVER}/${CERTIFICATE_PORT}" 2> /dev/null 98 | if [ $? -eq 0 ] 99 | then 100 | break 101 | else 102 | sleep 10s 103 | RETRY=$(expr ${RETRY} - 1) 104 | fi 105 | done 106 | 107 | if [[ $RETRY -le 0 ]] 108 | then 109 | echo "Could not connect to the certificate service '${CERTIFICATE_SERVER}'" 110 | exit 1 111 | fi 112 | 113 | # okay, the web service is available 114 | # but, we have a problem, when he runs behind a proxy ... 115 | # eg.: https://monitoring-proxy.tld/cert-cert-service 116 | # 117 | 118 | RETRY=30 119 | # wait for the certificate service health check behind a proxy 120 | # 121 | until [[ ${RETRY} -le 0 ]] 122 | do 123 | health=$(${CURL} \ 124 | --silent \ 125 | --location \ 126 | --insecure \ 127 | --write-out "%{http_code}\n" \ 128 | ${CERT_SERVICE_PROTOCOL}://${CERTIFICATE_SERVER}:${CERTIFICATE_PORT}${CERTIFICATE_PATH}/v2/health-check) 129 | 130 | if ( [[ $? -eq 0 ]] && [[ "${health}" == "healthy200" ]] ) 131 | then 132 | break 133 | fi 134 | 135 | echo "Wait for the health check for the certificate service on '${CERTIFICATE_SERVER}'" 136 | sleep 5s 137 | RETRY=$(expr ${RETRY} - 1) 138 | done 139 | 140 | if [[ $RETRY -le 0 ]] 141 | then 142 | echo "Could not a health check from the certificate service '${CERTIFICATE_SERVER}'" 143 | exit 1 144 | fi 145 | 146 | sleep 2s 147 | } 148 | 149 | 150 | api_request() { 151 | 152 | echo "" 153 | code=$(curl \ 154 | --user ${ICINGA2_API_USER}:${ICINGA2_API_PASSWORD} \ 155 | --silent \ 156 | --insecure \ 157 | --header 'Accept: application/json' \ 158 | https://${ICINGA2_MASTER}:${ICINGA2_API_PORT}/v1/status/ApiListener) 159 | 160 | if [[ $? -eq 0 ]] 161 | then 162 | 163 | num_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_endpoints") 164 | num_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_conn_endpoints") 165 | num_not_conn_endpoints=$(echo "${code}" | jq --raw-output ".results[].status.api.num_not_conn_endpoints") 166 | 167 | echo "api request are successfull" 168 | echo "endpoints summary:" 169 | echo "totaly: '${num_endpoints}' / connected: '${num_conn_endpoints}' / not connected: '${num_not_conn_endpoints}'" 170 | echo "" 171 | echo "connected endpoints: " 172 | echo "${code}" | jq --raw-output ".results[].status.api.conn_endpoints" 173 | echo "" 174 | echo "not connected endpoints: " 175 | echo "${code}" | jq --raw-output ".results[].status.api.not_conn_endpoints" 176 | echo "" 177 | echo "API zones:" 178 | echo "${code}" | jq --raw-output ".results[].status.api.zones" 179 | echo "" 180 | else 181 | echo ${code} 182 | echo "api request failed" 183 | fi 184 | } 185 | 186 | 187 | get_versions() { 188 | 189 | echo "" 190 | for s in $(docker-compose ps | grep icinga2 | awk '{print($1)}') 191 | do 192 | backend_network=$(docker network ls | egrep "*icinga2_backend*" | awk '{print $2}') 193 | 194 | ip=$(docker network inspect ${backend_network} | jq -r ".[].Containers | to_entries[] | select(.value.Name==\"${s}\").value.IPv4Address" | awk -F "/" '{print $1}') 195 | 196 | code=$(curl \ 197 | --user ${ICINGA2_API_USER}:${ICINGA2_API_PASSWORD} \ 198 | --silent \ 199 | --insecure \ 200 | --header 'Accept: application/json' \ 201 | https://${ip}:5665/v1/status/IcingaApplication) 202 | 203 | #echo "'${s}' : '${code}'" 204 | 205 | if [[ ! -z "${code}" ]] 206 | then 207 | version=$(echo "${code}" | jq --raw-output '.results[].status.icingaapplication.app.version' 2> /dev/null) 208 | node_name=$(echo "${code}" | jq --raw-output '.results[].status.icingaapplication.app.node_name' 2> /dev/null) 209 | 210 | printf "service %-20s (fqdn: %-30s / ip: %s) | version: %s\n" "${s}" "${node_name}" "${ip}" "${version}" 211 | else 212 | echo "WARNING: '${s}' returned no application status" 213 | 214 | docker logs ${s} 215 | fi 216 | done 217 | } 218 | 219 | 220 | inspect() { 221 | 222 | echo "" 223 | echo "inspect needed containers" 224 | for d in $(docker ps | tail -n +2 | awk '{print($1)}') 225 | do 226 | # docker inspect --format "{{lower .Name}}" ${d} 227 | c=$(docker inspect --format '{{with .State}} {{$.Name}} has pid {{.Pid}} {{end}}' ${d}) 228 | s=$(docker inspect --format '{{json .State.Health }}' ${d} | jq --raw-output .Status) 229 | 230 | printf "%-40s - %s\n" "${c}" "${s}" 231 | done 232 | } 233 | 234 | 235 | running_containers=$(docker ps | tail -n +2 | wc -l) 236 | 237 | if [[ ${running_containers} -eq 5 ]] || [[ ${running_containers} -gt 5 ]] 238 | then 239 | inspect 240 | wait_for_icinga_cert_service 241 | wait_for_icinga_instances 242 | 243 | get_versions 244 | api_request 245 | 246 | exit 0 247 | else 248 | echo "the test setup needs 5 containers" 249 | echo "only ${running_containers} running" 250 | echo "please run " 251 | echo " make compose-file" 252 | echo " docker-compose up -d" 253 | echo "before" 254 | echo "or check your system" 255 | 256 | exit 1 257 | fi 258 | -------------------------------------------------------------------------------- /tests/linter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HADOLINT_VERSION='1.16.3' 4 | HADOLINT_PATH='/usr/local/bin/hadolint' 5 | 6 | if ! [[ -e "${HADOLINT_PATH}_${HADOLINT_VERSION}" ]] 7 | then 8 | sudo curl \ 9 | --silent \ 10 | --location \ 11 | --output "${HADOLINT_PATH}_${HADOLINT_VERSION}" \ 12 | "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-x86_64" 13 | sudo chmod +x "${HADOLINT_PATH}_${HADOLINT_VERSION}" 14 | sudo ln -sf ${HADOLINT_PATH}_${HADOLINT_VERSION} ${HADOLINT_PATH} 15 | fi 16 | 17 | hadolint Dockerfile.base 18 | hadolint Dockerfile.master 19 | hadolint Dockerfile.satellite 20 | 21 | #shellcheck \ 22 | # --shell=sh \ 23 | # --external-sources \ 24 | # --exclude=SC1091,SC2039,SC2181 \ 25 | # rootfs/init/*.sh \ 26 | # rootfs/init/*/*.sh 27 | --------------------------------------------------------------------------------