From b3bea9196511d21e33f87edbb79410d4ab3e59f4 Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Fri, 24 Mar 2023 18:00:15 +0100 Subject: [PATCH] Update to 2023-03-24 18:00 --- roles/repo_wapt/defaults/main.yml | 2 +- roles/repo_wapt/tasks/main.yml | 2 +- roles/wapt_server/files/setup.py | 7 + roles/wapt_server/handlers/main.yml | 9 +- roles/wapt_server/tasks/conf.yml | 99 ++++++++++ roles/wapt_server/tasks/directories.yml | 12 ++ roles/wapt_server/tasks/facts.yml | 27 +++ roles/wapt_server/tasks/install.yml | 55 ++++++ roles/wapt_server/tasks/iptables.yml | 8 + roles/wapt_server/tasks/main.yml | 222 ++--------------------- roles/wapt_server/tasks/selinux.yml | 19 ++ roles/wapt_server/tasks/services.yml | 14 ++ roles/wapt_server/templates/wapt.conf.j2 | 109 +++++++---- roles/wapt_server/vars/RedHat-8.yml | 2 +- 14 files changed, 338 insertions(+), 249 deletions(-) create mode 100644 roles/wapt_server/files/setup.py create mode 100644 roles/wapt_server/tasks/conf.yml create mode 100644 roles/wapt_server/tasks/directories.yml create mode 100644 roles/wapt_server/tasks/facts.yml create mode 100644 roles/wapt_server/tasks/install.yml create mode 100644 roles/wapt_server/tasks/iptables.yml create mode 100644 roles/wapt_server/tasks/selinux.yml create mode 100644 roles/wapt_server/tasks/services.yml diff --git a/roles/repo_wapt/defaults/main.yml b/roles/repo_wapt/defaults/main.yml index 4e5ba82..3fc5c00 100644 --- a/roles/repo_wapt/defaults/main.yml +++ b/roles/repo_wapt/defaults/main.yml @@ -1,2 +1,2 @@ --- -wapt_version: 1.8 +wapt_version: 2.3 diff --git a/roles/repo_wapt/tasks/main.yml b/roles/repo_wapt/tasks/main.yml index a08194b..beb6fcd 100644 --- a/roles/repo_wapt/tasks/main.yml +++ b/roles/repo_wapt/tasks/main.yml @@ -3,7 +3,7 @@ yum_repository: name: wapt description: WAPT - baseurl: https://wapt.tranquil.it/centos$releasever/wapt-{{ wapt_version }}/ + baseurl: https://wapt.tranquil.it/redhat$releasever/wapt-{{ wapt_version }}/ gpgcheck: False tags: repo,wapt diff --git a/roles/wapt_server/files/setup.py b/roles/wapt_server/files/setup.py new file mode 100644 index 0000000..bd3bc5a --- /dev/null +++ b/roles/wapt_server/files/setup.py @@ -0,0 +1,7 @@ +#!/usr/bin/waptpython + +import sys +sys.path.append('/opt/wapt') +from waptpackage import WaptLocalRepo +repo = WaptLocalRepo("/var/www/html/wapt") +repo.update_packages_index() diff --git a/roles/wapt_server/handlers/main.yml b/roles/wapt_server/handlers/main.yml index 23d74e3..4ff281f 100644 --- a/roles/wapt_server/handlers/main.yml +++ b/roles/wapt_server/handlers/main.yml @@ -1,13 +1,12 @@ --- -- name: restart postgresql - service: name=postgresql-9.6 state=restarted - - name: restart nginx service: name=nginx state=restarted - name: restart wapt service: name={{ item }} state=restarted - with_items: + loop: - waptserver - #- wapttasks + - wapttasks + - waptservice + - wapttftpserver diff --git a/roles/wapt_server/tasks/conf.yml b/roles/wapt_server/tasks/conf.yml new file mode 100644 index 0000000..ce863c7 --- /dev/null +++ b/roles/wapt_server/tasks/conf.yml @@ -0,0 +1,99 @@ +--- + +- name: Create wapt DB user + postgresql_user: + db: postgres + name: "{{ wapt_db_user }}" + password: "{{ wapt_db_pass }}" + login_host: "{{ wapt_db_server }}" + login_user: sqladmin + login_password: "{{ pg_admin_pass }}" + tags: wapt + +- name: Create the PostgreSQL database + postgresql_db: + name: wapt + encoding: UTF-8 + template: template0 + owner: "{{ wapt_db_user }}" + login_host: "{{ wapt_db_server }}" + login_user: sqladmin + login_password: "{{ pg_admin_pass }}" + tags: wapt + +- name: Enable the hstore extension + postgresql_ext: + db: "{{ wapt_db_name }}" + login_host: "{{ wapt_db_server }}" + login_user: sqladmin + login_password: "{{ pg_admin_pass }}" + name: hstore + tags: wapt + +- name: Configure WAPT server + ini_file: path=/opt/wapt/conf/waptserver.ini section=options option={{ item.option }} value={{ item.value }} + with_items: + - option: db_name + value: "{{ wapt_db_name }}" + - option: db_host + value: "{{ wapt_db_server }}" + - option: db_user + value: "{{ wapt_db_user }}" + - option: db_password + value: "{{ wapt_db_pass }}" + - option: waptwua_folder + value: /var/www/html/waptwua + - option: server_uuid + value: "{{ inventory_hostname | to_uuid }}" + - option: allow_unauthenticated_connect + value: 'False' + - option: allow_unauthenticated_registration + value: 'False' + - option: secret_key + value: "{{ wapt_secret_key }}" + - option: use_kerberos + value: 'False' + notify: restart wapt + tags: wapt + +- name: Configure system proxy + ini_file: path=/opt/wapt/conf/waptserver.ini section=options option=http_proxy value={{ system_proxy }} + when: system_proxy is defined and system_proxy != '' + notify: restart wapt + tags: wapt + +- name: Check if admin password is set + command: grep -qP '^wapt_password' /opt/wapt/conf/waptserver.ini + ignore_errors: True + register: wapt_admin_pass_set + changed_when: False + tags: wapt + +- when: wapt_admin_pass_set.rc != 0 + block: + - name: Hash the WAPT admin password + command: /opt/wapt/bin/python -c 'from passlib.hash import pbkdf2_sha256; print(pbkdf2_sha256.hash("admin".encode("utf8")))' + register: wapt_admin_pass_hash + changed_when: False + + - set_fact: wapt_admin_pass_hash={{ wapt_admin_pass_hash.stdout }} + + - name: Set default admin password + ini_file: path=/opt/wapt/conf/waptserver.ini section=options option=wapt_password value={{ wapt_admin_pass_hash }} + notify: restart wapt + + tags: wapt + +- name: Set correct ownership for wapt configuration + file: path=/opt/wapt/conf/waptserver.ini owner=wapt mode=0600 + tags: wapt + +- name: Deploy nginx config + template: src={{ item.src }}.j2 dest={{ item.dest }} + loop: + - src: nginx.conf + dest: /etc/nginx/nginx.conf + - src: wapt.conf + dest: /etc/nginx/conf.d/wapt.conf + notify: restart nginx + tags: wapt diff --git a/roles/wapt_server/tasks/directories.yml b/roles/wapt_server/tasks/directories.yml new file mode 100644 index 0000000..aa38ce8 --- /dev/null +++ b/roles/wapt_server/tasks/directories.yml @@ -0,0 +1,12 @@ +--- + +- name: Create directories + file: path={{ item.path }} state=directory mode={{ item.mode | default(omit) }} owner={{ item.owner | default(omit) }} group={{ item.group | default(omit) }} + loop: + - path: /opt/wapt + mode: 755 + - path: /opt/wapt/meta + mode: 700 + - path: /opt/wapt/backup + mode: 700 + tags: wapt diff --git a/roles/wapt_server/tasks/facts.yml b/roles/wapt_server/tasks/facts.yml new file mode 100644 index 0000000..6231011 --- /dev/null +++ b/roles/wapt_server/tasks/facts.yml @@ -0,0 +1,27 @@ +--- + +- include_vars: "{{ item }}" + with_first_found: + - "{{ role_path }}/vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" + - "{{ role_path }}/vars/{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml" + - "{{ role_path }}/vars/{{ ansible_distribution }}.yml" + - "{{ role_path }}/vars/{{ ansible_os_family }}.yml" + tags: wapt + +- when: wapt_db_pass is not defined + name: Generate a random pass for the database + block: + - import_tasks: ../includes/get_rand_pass.yml + vars: + - pass_file: "/opt/wapt/meta/ansible_dbpass" + - set_fact: wapt_db_pass={{ rand_pass }} + tags: wapt + +- when: wapt_secret_key is not defined + name: Generate a random secret_key + block: + - import_tasks: ../includes/get_rand_pass.yml + vars: + - pass_file: "/opt/wapt/meta/ansible_secret_key" + - set_fact: wapt_secret_key={{ rand_pass }} + tags: wapt diff --git a/roles/wapt_server/tasks/install.yml b/roles/wapt_server/tasks/install.yml new file mode 100644 index 0000000..6b0b674 --- /dev/null +++ b/roles/wapt_server/tasks/install.yml @@ -0,0 +1,55 @@ +--- + +# On RHEL8, enable nginx 1.20 module +- name: Enable nginx 1.20 module + command: dnf -y module enable nginx:1.20 + when: ansible_os_family == 'RedHat' and ansible_distribution_major_version is version('8', '=') + tags: wapt + +- name: Install packages + yum: name={{ wapt_packages }} + tags: wapt + +- name: Create SSL directory + file: path=/var/www/html/ssl state=directory mode=750 owner=wapt group=nginx + tags: wapt + +- name: Create an empty license file + file: path=/var/www/html/licences.json state=touch mode=644 owner=wapt + changed_when: False + tags: wapt + +- name: Create unit snippet dir + file: path=/etc/systemd/system/waptserver.service.d state=directory + tags: wapt + +- name: Tune wapt to restart indefinitely + copy: + content: | + [Service] + Restart=on-failure + StartLimitInterval=0 + RestartSec=20 + dest: /etc/systemd/system/waptserver.service.d/restart.conf + register: wapt_unit + tags: wapt + +- name: Reload systemd + systemd: daemon_reload=True + when: wapt_unit.changed + tags: wapt + +- name: Deploy pre and post backup scripts + template: src={{ item }}-backup.sh.j2 dest=/etc/backup/{{ item }}.d/wapt.sh mode=0700 + with_items: + - pre + - post + tags: wapt + +- name: Copy setup script + copy: src=setup.py dest=/opt/wapt/bin/setup.py mode=755 + tags: wapt + +- name: Run setup script + command: /opt/wapt/bin/setup.py + tags: wapt diff --git a/roles/wapt_server/tasks/iptables.yml b/roles/wapt_server/tasks/iptables.yml new file mode 100644 index 0000000..2294d3c --- /dev/null +++ b/roles/wapt_server/tasks/iptables.yml @@ -0,0 +1,8 @@ +--- + +- name: Handle ports + iptables_raw: + name: wapt_ports + state: "{{ (wapt_src_ip is defined and wapt_src_ip | length > 0) | ternary('present','absent') }}" + rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ wapt_ports | join(',') }} -s {{ wapt_src_ip | join(',') }} -j ACCEPT" + tags: wapt diff --git a/roles/wapt_server/tasks/main.yml b/roles/wapt_server/tasks/main.yml index 913e2ee..499e96a 100644 --- a/roles/wapt_server/tasks/main.yml +++ b/roles/wapt_server/tasks/main.yml @@ -1,218 +1,24 @@ --- -- include_vars: "{{ item }}" - with_first_found: - - vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml - - vars/{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml - - vars/{{ ansible_distribution }}.yml - - vars/{{ ansible_os_family }}.yml - tags: wapt +- include_tasks: directories.yml + tags: always -- name: Install packages - yum: name={{ wapt_packages }} - tags: wapt +- include_tasks: facts.yml + tags: always -- name: Create directories - file: path={{ item.path }} state=directory mode={{ item.mode | default(omit) }} owner={{ item.owner | default(omit) }} group={{ item.group | default(omit) }} - loop: - - path: /opt/wapt/meta - mode: 700 - - path: /opt/wapt/backup - mode: 700 - - path: /var/www/html/ssl - mode: 750 - owner: wapt - group: nginx - tags: wapt +- include_tasks: install.yml + tags: always -- import_tasks: ../includes/get_rand_pass.yml - vars: - - pass_file: "/opt/wapt/meta/ansible_dbpass" - when: wapt_db_pass is not defined - tags: wapt -- set_fact: wapt_db_pass={{ rand_pass }} - when: wapt_db_pass is not defined - tags: wapt - -- name: Create wapt DB user - postgresql_user: - db: postgres - name: "{{ wapt_db_user }}" - password: "{{ wapt_db_pass }}" - login_host: "{{ wapt_db_server }}" - login_user: sqladmin - login_password: "{{ pg_admin_pass }}" - tags: wapt - -- name: Create the PostgreSQL database - postgresql_db: - name: wapt - encoding: UTF-8 - template: template0 - owner: "{{ wapt_db_user }}" - login_host: "{{ wapt_db_server }}" - login_user: sqladmin - login_password: "{{ pg_admin_pass }}" - tags: wapt - -- name: Enable the hstore extension - postgresql_ext: - db: "{{ wapt_db_name }}" - login_host: "{{ wapt_db_server }}" - login_user: sqladmin - login_password: "{{ pg_admin_pass }}" - name: hstore - tags: wapt - -- name: Configure SELinux - seboolean: name={{ item }} state=True persistent=True - with_items: - - httpd_can_network_connect - - httpd_setrlimit +- include_tasks: selinux.yml when: ansible_selinux.status == 'enabled' - tags: wapt + tags: always -- name: Set SELinux context on repo dir - sefcontext: - target: '/var/www/html/wapt(\-host)?(/.*)?' - setype: httpd_sys_content_t - when: ansible_selinux.status == 'enabled' - tags: wapt +- include_tasks: conf.yml + tags: always -- name: Reset SELinux contexts - command: restorecon -Rv /var/www/html - changed_when: False - tags: wapt - -- import_tasks: ../includes/get_rand_pass.yml - vars: - - pass_file: "/opt/wapt/meta/ansible_secret_key" - tags: wapt -- set_fact: wapt_secret_key={{ rand_pass }} - tags: wapt - -- name: Configure WAPT server - ini_file: path=/opt/wapt/conf/waptserver.ini section=options option={{ item.option }} value={{ item.value }} - with_items: - - option: db_name - value: "{{ wapt_db_name }}" - - option: db_host - value: "{{ wapt_db_server }}" - - option: db_user - value: "{{ wapt_db_user }}" - - option: db_password - value: "{{ wapt_db_pass }}" - - option: waptwua_folder - value: /var/www/html/waptwua - - option: server_uuid - value: "{{ inventory_hostname | to_uuid }}" - - option: allow_unauthenticated_connect - value: 'False' - - option: allow_unauthenticated_registration - value: 'False' - - option: secret_key - value: "{{ wapt_secret_key }}" - - option: use_kerberos - value: 'False' - notify: restart wapt - tags: wapt - -- name: Create unit snippet dir - file: path=/etc/systemd/system/waptserver.service.d state=directory - tags: wapt - -- name: Tune wapt to restart indefinitely - copy: - content: | - [Service] - Restart=on-failure - StartLimitInterval=0 - RestartSec=20 - dest: /etc/systemd/system/waptserver.service.d/restart.conf - register: wapt_unit - tags: wapt - -- name: Reload systemd - systemd: daemon_reload=True - when: wapt_unit.changed - tags: wapt - -- name: Configure system proxy - ini_file: path=/opt/wapt/conf/waptserver.ini section=options option=http_proxy value={{ system_proxy }} - when: system_proxy is defined and system_proxy != '' - notify: restart wapt - tags: wapt - -- name: Check if admin password is set - command: grep -qP '^wapt_password' /opt/wapt/conf/waptserver.ini - ignore_errors: True - register: wapt_admin_pass_set - changed_when: False - tags: wapt - -- name: Hash the WAPT admin password - command: python -c 'from passlib.hash import pbkdf2_sha256; print pbkdf2_sha256.hash("admin".encode("utf8"))' - register: wapt_admin_pass_hash - environment: - - PYTHONPATH: /opt/wapt/lib/python2.7/site-packages/ - when: wapt_admin_pass_set.rc != 0 - changed_when: False - tags: wapt -- set_fact: wapt_admin_pass_hash={{ wapt_admin_pass_hash.stdout }} - when: wapt_admin_pass_set.rc != 0 - tags: wapt -- name: Set default admin password - ini_file: path=/opt/wapt/conf/waptserver.ini section=options option=wapt_password value={{ wapt_admin_pass_hash }} - when: wapt_admin_pass_set.rc != 0 - notify: restart wapt - tags: wapt - -- name: Set correct ownership for wapt configuration - file: path=/opt/wapt/conf/waptserver.ini owner=wapt mode=0600 - tags: wapt - -- name: Deploy nginx config - template: src={{ item.src }}.j2 dest={{ item.dest }} - with_items: - - src: nginx.conf - dest: /etc/nginx/nginx.conf - - src: wapt.conf - dest: /etc/nginx/conf.d/wapt.conf - notify: restart nginx - tags: wapt - -- name: Start and enable nginx - service: name=nginx state=started enabled=True - tags: wapt - -- name: Start and enable WAPT services - service: name={{ item }} state=started enabled=True - with_items: - - waptserver - #- wapttasks - tags: wapt - -- name: Handle ports - iptables_raw: - name: wapt_ports - state: "{{ (wapt_src_ip is defined and wapt_src_ip | length > 0) | ternary('present','absent') }}" - rules: "-A INPUT -m state --state NEW -p tcp -m multiport --dports {{ wapt_ports | join(',') }} -s {{ wapt_src_ip | join(',') }} -j ACCEPT" +- include_tasks: iptables.yml when: iptables_manage | default(True) - tags: wapt + tags: always -- name: Create DB dump directory - file: path=/opt/wapt/backup state=directory mode=0700 - tags: wapt - -- name: Deploy pre and post backup scripts - template: src={{ item }}-backup.sh.j2 dest=/etc/backup/{{ item }}.d/wapt.sh mode=0755 - with_items: - - pre - - post - tags: wapt - -- name: Remove tmp and obsolete files - file: path={{ item }} state=absent - loop: - - /opt/wapt/db_dumps - tags: wapt +- include_tasks: services.yml + tags: always diff --git a/roles/wapt_server/tasks/selinux.yml b/roles/wapt_server/tasks/selinux.yml new file mode 100644 index 0000000..e1a0882 --- /dev/null +++ b/roles/wapt_server/tasks/selinux.yml @@ -0,0 +1,19 @@ +--- + +- name: Configure SELinux + seboolean: name={{ item }} state=True persistent=True + with_items: + - httpd_can_network_connect + - httpd_setrlimit + tags: wapt + +- name: Set SELinux context on repo dir + sefcontext: + target: '/var/www/html/(wapt(\-host|ua)?|wads)(/.*)?' + setype: httpd_sys_content_t + tags: wapt + +- name: Reset SELinux contexts + command: restorecon -Rv /var/www/html + changed_when: False + tags: wapt diff --git a/roles/wapt_server/tasks/services.yml b/roles/wapt_server/tasks/services.yml new file mode 100644 index 0000000..3caa6c0 --- /dev/null +++ b/roles/wapt_server/tasks/services.yml @@ -0,0 +1,14 @@ +--- + +- name: Start and enable nginx + service: name=nginx state=started enabled=True + tags: wapt + +- name: Start and enable WAPT services + service: name={{ item }} state=started enabled=True + loop: + - waptserver + - wapttasks + - waptservice + - wapttftpserver + tags: wapt diff --git a/roles/wapt_server/templates/wapt.conf.j2 b/roles/wapt_server/templates/wapt.conf.j2 index bf7a8b5..f8dfda8 100644 --- a/roles/wapt_server/templates/wapt.conf.j2 +++ b/roles/wapt_server/templates/wapt.conf.j2 @@ -11,46 +11,89 @@ server { index index.html; - location ~ ^/wapt.* { - proxy_set_header Cache-Control "store, no-cache, must-revalidate, post-check=0, pre-check=0"; - proxy_set_header Pragma "no-cache"; - proxy_set_header Expires "Sun, 19 Nov 1978 05:00:00 GMT"; + server_tokens off; + + client_max_body_size 12288m; + client_body_timeout 1800; + + # sub instances + include "/opt/wapt/conf/wapt.d/*.conf"; + + location /static { + alias "/opt/wapt/waptserver/static"; + } + + location /ssl { + alias "/var/www/html/ssl"; + } + + # not protected URL + location ~ ^/(wapt/waptsetup.*.exe|wapt/waptagent/.*|wapt/waptagent.exe|wapt/waptdeploy.exe|sync.json|rules.json|licences.json)$ { + add_header Cache-Control "store, no-cache, must-revalidate, post-check=0, pre-check=0"; + add_header Pragma "no-cache"; root "/var/www/html"; } + # not protected URL + location /wads { + alias "/var/www/html/wads"; + } + + # SSL protected URL + location ~ ^/(wapt/.*|waptwua/.*|wapt-diff-repos/.*)$ { + add_header Cache-Control "store, no-cache, must-revalidate, post-check=0, pre-check=0"; + add_header Pragma "no-cache"; + + # be sure these headers are not forwarded + proxy_set_header X-Ssl-Client-Dn ""; + proxy_set_header X-Ssl-Authenticated ""; + + root "/var/www/html"; + } + + # we don't want to expose our list of computers in case someone scan this folder. + location /wapt-host/Packages { + return 403; + } + + location ~ ^/(wapt-host/.*)$ { + log_not_found off; + add_header Cache-Control "store, no-cache, must-revalidate, post-check=0, pre-check=0"; + add_header Pragma "no-cache"; + + # be sure these headers are not forwarded + proxy_set_header X-Ssl-Client-Dn ""; + proxy_set_header X-Ssl-Authenticated ""; + + root "/var/www/html"; + } + + + location ~ ^/.*_kerberos$ { + return 403; + } + location / { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + add_header X-Remote-IP $remote_addr; + proxy_http_version 1.1; + proxy_request_buffering off; proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:8080; + } - client_max_body_size 4096m; - client_body_timeout 1800; + location /socket.io { + proxy_http_version 1.1; + proxy_request_buffering off; - location /add_host_kerberos { - return 403; - } + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - location ~ ^/(api/v3/upload_packages|api/v3/upload_hosts/|upload_waptsetup) { - proxy_pass http://127.0.0.1:8080; - client_max_body_size 4096m; - client_body_timeout 1800; - } - - location /wapt-host/Packages { - return 403; - } - - location / { - proxy_pass http://127.0.0.1:8080; - } - - location /socket.io { - proxy_http_version 1.1; - proxy_buffering off; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_pass http://127.0.0.1:8080/socket.io; - } + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_pass http://127.0.0.1:8080/socket.io; } } diff --git a/roles/wapt_server/vars/RedHat-8.yml b/roles/wapt_server/vars/RedHat-8.yml index ffb6428..defbfd1 100644 --- a/roles/wapt_server/vars/RedHat-8.yml +++ b/roles/wapt_server/vars/RedHat-8.yml @@ -2,6 +2,6 @@ wapt_packages: - tis-waptserver -# - tis-waptsetup + - tis-waptsetup - postgresql14 - python3-psycopg2 # Needed to manage PG with ansible