diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..7f9b2cb --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,46 @@ +--- +# directory_logrotate_config: /etc/logrotate.d +install_glpi: 'true' +glpi_installed: false +# logfile_max_size: 10 # must be specified in MB (Mega Bytes) +# logrotate_configuration: [] # Global var for usage within group/host vars + +docker_image_name_glpi: nofusscomputing/docker-glpi +docker_image_tag_glpi: dev + +docker_container_name_glpi: glpi +# mysql_unix_socket: /run/mysql/mariadb/mysqld.sock +mysql_unix_socket: /var/lib/docker/volumes/socket-mysql/_data/mysqld.sock +mysql_login_user: root +mysql_login_password: admin + +glpi_plugins: + - filename: fail2ban_1.0.2-1.upstream1_all.deb + #url: https://github.com/pluginsGLPI/formcreator/releases/download/2.13.6/glpi-formcreator-2.13.6.tar.bz2 + url: https://api.github.com/repos/pluginsGLPI/formcreator/releases/tags/2.13.6 + + - filename: glpi-glpiinventory-1.2.3.tar.bz2 + #url: https://github.com/glpi-project/glpi-inventory-plugin/releases/download/1.2.3/glpi-glpiinventory-1.2.3.tar.bz2 + url: https://api.github.com/repos/glpi-project/glpi-inventory-plugin/releases/tags/1.2.3 + + # - filename: glpi-actualtime-2.1.0.tar.tgz + # url: https://api.github.com/repos/ticgal/actualtime/releases/tags/2.1.0/glpi-actualtime-2.1.0.tar.tgz + + +mysql_database_glpi: glpi + +# Configuration Example +# logrotate: +# - name: docker # Mandatory, used as logrotate difinition file name +# path: '/var/lib/docker/containers/*/*.log' # Mandatory, path to the logfile +# su: ingress ingress # Optional,, string user and group for log permissions +# interval: daily # optional example daily, weekly, monthly default=daily +# keep: # Optional, int, How many logs to keep default=7 +# size: 10 # Optional, max size of logfile in Mega Bytes. DONT specify unit. default={{}} +# compress: # Optional, bool default=true +# delaycompress: # Optional, bool, delay logfile compression default=true +# postrotate: 'docker restart $(docker ps -q)' # Optional, Command to run post rotate default=not defined +# create: # Optional, default=not defined +# mode: 640 # Mandatory, filemode +# owner: root # Mandatory, logfile owner +# group: adm # Mandatory, logfile group owner diff --git a/handlers/main.yaml b/handlers/main.yaml new file mode 100644 index 0000000..65abc11 --- /dev/null +++ b/handlers/main.yaml @@ -0,0 +1,29 @@ +--- +# - name: Log Rotate Configuration files +# ansible.builtin.template: +# src: definition.j2 +# dest: "{{ directory_logrotate_config }}/{{ item.name }}" +# owner: root +# mode: '0644' +# force: true +# loop: "{{ logrotate_configuration }}" +# listen: 'configure_logrotate' +# notify: restart_logrotate +# when: logrotate_installed | bool + + +# - name: Restart logrotate +# ansible.builtin.service: +# name: logrotate +# state: restarted +# listen: restart_logrotate +# when: logrotate_installed | bool + +- name: Restart GLPI + community.docker.docker_container: + name: "{{ docker_container_name_glpi }}" + state: started + restart: true + listen: restart_glpi + when: > + glpi_installed | bool diff --git a/meta/main.yaml b/meta/main.yaml new file mode 100644 index 0000000..31ab5e5 --- /dev/null +++ b/meta/main.yaml @@ -0,0 +1,13 @@ +galaxy_info: + role_name: nfc_glpi + author: No Fuss Computing + description: |- + A universal role to install and configure a glpi. + + This role is also desiged so that it can be included within other roles. + + issue_tracker_url: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi + + license: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi/-/blob/master/LICENSE + + min_ansible_version: '1.2' diff --git a/tasks/configure.yaml b/tasks/configure.yaml new file mode 100644 index 0000000..e72f601 --- /dev/null +++ b/tasks/configure.yaml @@ -0,0 +1,111 @@ +--- +- name: Clear Any downloaded files + ansible.builtin.file: + name: "/tmp/ansible" + state: absent + #loop: "{{ glpi_plugins }}" + +- name: Clear Any downloaded files + ansible.builtin.file: + name: "/tmp/ansible" + state: directory + #loop: "{{ glpi_plugins }}" + +# - name: Download Plugins +# ansible.builtin.get_url: +# url: "{{ item.url }}" +# dest: "/tmp/{{ item.filename }}" +# loop: "{{ glpi_plugins }}" + +# - name: Download plugins +# ansible.builtin.command: +# cmd: "bash -c echo $({{ item.url }})" +# loop: "{{ glpi_plugins }}" + +# wget https://github.com/pluginsGLPI/formcreator/releases/download/2.13.6/glpi-formcreator-2.13.6.tar.bz2 -O /tmp/plugin-form-creator.tar.bz2 +# tar -xjf /tmp/plugin-form-creator.tar.bz2 -C /var/lib/docker/volumes/glpi_glpi_plugins/_data/ + +# wget https://github.com/glpi-project/glpi-inventory-plugin/releases/download/1.2.3/glpi-glpiinventory-1.2.3.tar.bz2 -O /tmp/glpi-glpiinventory-1.2.3.tar.bz2 +# tar -xjf /tmp/glpi-glpiinventory-1.2.3.tar.bz2 -C /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# chown www-data:www-data -R /var/lib/docker/volumes/glpi_glpi_plugins/_data/ + +- name: Install bzip + ansible.builtin.apt: + name: "{{ item }}" + state: present + loop: "{{ apps }}" + vars: + apps: + - bzip2 + - jq + - wget + + +# - name: Example clone of a single branch +# ansible.builtin.git: +# repo: "{{ item.repo }}.git" +# dest: "/var/lib/docker/volumes/plugins_glpi/_data/{{ item.name }}" +# single_branch: true +# version: "{{ item.version }}" +# depth: 1 +# force: true +# loop: "{{ plugins }}" +# vars: +# plugins: +# - name: actualtime +# repo: https://github.com/ticgal/actualtime +# version: 2.1.0 + +# - name: glpiinventory +# repo: https://github.com/glpi-project/glpi-inventory-plugin +# version: 1.2.3 +# # for creator doesnt work +# # - name: formcreator +# # repo: https://github.com/pluginsGLPI/formcreator +# # version: 2.13.6 + +# - name: geninventorynumber +# repo: https://github.com/pluginsGLPI/geninventorynumber +# version: 2.8.3 + +# - name: releases +# repo: https://github.com/InfotelGLPI/releases +# version: 2.0.3 + +# - name: phpsaml +# repo: https://github.com/DonutsNL/phpsaml +# # version: e7357a49ca9f0b612bc28879a0c703cdbfc4463b +# version: master + +# - name: Download and Extract the plugins +# ansible.builtin.shell: +# cmd: | +# export URL=$(curl -s {{ item.url }} | jq .assets[0].browser_download_url | tr -d \"); +# wget $URL -O /tmp/ansible/$(basename ${URL}); +# tar -xjf /tmp/ansible/$(basename ${URL}) -C /var/lib/docker/volumes/plugins_glpi/_data/; +# loop: "{{ glpi_plugins }}" +# changed_when: false + + +- name: Fix file perms + ansible.builtin.command: + cmd: chown www-data:www-data -R /var/lib/docker/volumes/plugins_glpi/_data/ + changed_when: false + +# - name: Unarchive a file that needs to be downloaded (added in 2.0) +# ansible.builtin.unarchive: +# src: /tmp/{{ item.filename }} +# dest: /var/lib/docker/volumes/plugins_glpi/_data/ +# remote_src: true +# extra_opts: +# - -j +# loop: "{{ glpi_plugins }}" + +- name: Clear Any downloaded files + ansible.builtin.file: + name: "{{ item.filename }}" + state: absent + loop: "{{ glpi_plugins }}" + +- name: Reload logroate if required + ansible.builtin.meta: flush_handlers diff --git a/tasks/install.yaml b/tasks/install.yaml new file mode 100644 index 0000000..c9df8c6 --- /dev/null +++ b/tasks/install.yaml @@ -0,0 +1,150 @@ +--- +- name: GPLI Docker Container + ansible.builtin.include_role: + name: docker_management + vars: + docker_images: + - name: "{{ docker_image_name_glpi }}" + tag: "{{ docker_image_tag_glpi }}" + + docker_networks: + - name: "{{ docker_container_name_glpi }}-access" + internal: false # this needs to be added to the docker role + - name: "{{ docker_container_name_glpi }}-smtp-access" + internal: true + + docker_containers: + - name: "{{ docker_container_name_glpi }}" + image: "{{ docker_image_name_glpi }}:{{ docker_image_tag_glpi }}" + env: + TIMEZONE: UTC + networks: + - name: "{{ docker_container_name_glpi }}-access" + - name: "ingress-access" + - name: "{{ docker_container_name_glpi }}-smtp-access" + - name: ldap-access + - name: mysql-access + # published_ports: + # - 80:80 + volumes: + - /usr/share/zoneinfo/Etc/UTC:/etc/timezone:ro + - /usr/share/zoneinfo/Etc/UTC:/etc/localtime:ro + - "config_{{ docker_container_name_glpi }}:/var/www/html/config" + - "data_{{ docker_container_name_glpi }}:/var/www/html/files" + - "log_{{ docker_container_name_glpi }}:/var/log" + - "marketplace_{{ docker_container_name_glpi }}:/var/www/html/marketplace" + - "plugins_{{ docker_container_name_glpi }}:/var/www/html/plugins" + + docker_volumes: + - name: "plugins_{{ docker_container_name_glpi }}" + - name: "data_{{ docker_container_name_glpi }}" + - name: "config_{{ docker_container_name_glpi }}" + - name: "marketplace_{{ docker_container_name_glpi }}" + - name: "log_{{ docker_container_name_glpi }}" + - name: "varlog_{{ docker_container_name_glpi }}" + + +- name: Create GLPI database + community.mysql.mysql_db: + name: "{{ mysql_database_glpi }}" + state: present + login_unix_socket: "{{ mysql_unix_socket }}" + login_user: "{{ mysql_login_user }}" + login_password: "{{ mysql_login_password }}" + login_host: "{{ mysql_login_host | default('') }}" + config_file: '' + + +- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2 + community.mysql.mysql_user: + state: "{{ item.state | default('present') }}" + name: "{{ item.name }}" + password: "{{ item.password }}" + host: "{{ item.host | default('localhost') }}" + priv: "{{ item.priv | default(omit) | from_yaml }}" + update_password: "{{ item.update_password | default('on_create') }}" + login_host: "{{ mysql_login_host | default('') }}" + login_unix_socket: "{{ mysql_unix_socket }}" + login_user: "{{ mysql_login_user }}" + login_password: "{{ mysql_login_password }}" + config_file: '' + loop: "{{ database_mysql_users }}" + vars: + database_mysql_users: + - name: glpi + password: admin + host: '%' + priv: + 'glpi.*': 'ALL,GRANT' + +# sudo cp -r /var/www/html/glpi/config/* /var/lib/docker/volumes/glpi_config_glpi/_data/ +# sudo cp -r /var/www/html/glpi/files/* /var/lib/docker/volumes/glpi_data_glpi/_data/ +# sudo cp -r /var/www/html/glpi/plugins/* /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# sudo cp -r /var/www/html/glpi/marketplace/* /var/lib/docker/volumes/glpi_marketplace_glpi/_data/ + + +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_config_glpi/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_data_glpi/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_marketplace_glpi/_data/ + +- name: Add fail2ban filters + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + mode: '760' + owner: root + group: root + loop: "{{ the_files }}" + # notify: reload_fail2ban + when: > + install_fail2ban | default(false) | bool + vars: + the_files: + - src: fail2ban.filter.conf + dest: "/etc/fail2ban/filter.d/glpi.local" + - src: fail2ban.filter.conf + dest: "/etc/fail2ban/filter.d/glpi-api.local" + + +- name: "Fail2Ban Jail for GLPI" + ansible.builtin.include_role: + name: nfc_firewall + when: > + install_fail2ban | default(false) | bool + vars: + fail2ban: + config: + - name: "glpi-{{ docker_container_name_glpi }}" + sub_path: jail.d + sections: + DEFAULT: + "glpi_log": "/var/lib/docker/volumes/data_{{ docker_container_name_glpi }}/_data/_log/event.log" + glpi: + enabled: true + mode: polling + chain: DOCKER-USER + port: http,https + logpath: "%(glpi_log)s" + filter: glpi + findtime: 600 + maxretry: 5 + - name: "api_glpi-{{ docker_container_name_glpi }}" + sub_path: jail.d + sections: + DEFAULT: + "api_glpi_log": "/var/lib/docker/volumes/log_{{ docker_container_name_glpi }}/_data/apache2/access-glpi.log" + api_glpi: + enabled: true + mode: polling + chain: DOCKER-USER + port: http,https + logpath: "%(api_glpi_log)s" + filter: glpi-api + findtime: 600 + maxretry: 5 + + +- name: Task Final playbook variables + ansible.builtin.set_fact: + glpi_installed: true diff --git a/tasks/main.yaml b/tasks/main.yaml new file mode 100644 index 0000000..8f54866 --- /dev/null +++ b/tasks/main.yaml @@ -0,0 +1,33 @@ +--- +- name: Install GLPI + ansible.builtin.include_tasks: + file: install.yaml + apply: + tags: + - always + tags: + - always + when: > + install_glpi | bool + and + not glpi_installed | bool + + + +- name: Configure Log Rotate + ansible.builtin.include_tasks: + file: configure.yaml + apply: + tags: + - always + tags: + - always + when: glpi_installed | bool +# and +# ansible_os_family == "Debian" +# and +# ( +# logrotate is defined +# and +# logrotate | default([]) | length | int > 0 +# ) diff --git a/templates/fail2ban.filter-api.conf b/templates/fail2ban.filter-api.conf new file mode 100644 index 0000000..4224099 --- /dev/null +++ b/templates/fail2ban.filter-api.conf @@ -0,0 +1,15 @@ +# +# Fail2ban Filter, GLPI API Denied access +# +# Managed By: Ansible +# Role: nfc_glpi +# +# Do not edit this file directly as it will be automagically updated by ansible. +# to make changes update the ansible play that deploys this file. +[Init] +maxlines = 2 + +[Definition] + +failregex = ^([\d|\.?]{1,3}).+apirest.php.+"\s40\d\s\d{1,5} + diff --git a/templates/fail2ban.filter.conf b/templates/fail2ban.filter.conf new file mode 100644 index 0000000..faf7b68 --- /dev/null +++ b/templates/fail2ban.filter.conf @@ -0,0 +1,17 @@ +# +# Fail2ban Filter, GLPI +# +# Managed By: Ansible +# Role: nfc_glpi +# +# Do not edit this file directly as it will be automagically updated by ansible. +# to make changes update the ansible play that deploys this file. +[Init] +maxlines = 2 + +[Definition] +# failregex = ^(?P\d{4}-\d{2}-\d{2}\s?\d{2}:\d{2}:\d{2})\s+?\S+\n?\[login\]\s+?[\d+]?:?[\s+]?Failed\s+?login\s+?for\s(?P.+)\s+?from\s+?IP\s+?(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$ + +# failregex = ^(.+)ogin] \d+: Failed login for (.+) from IP (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$ +failregex = ^.*?(Failed login for)[\S\s]+(from IP) .*$ +# ^.*\s(\[\S).*?(Failed login for) \S+ (from IP) .*$