This is an automated email from the ASF dual-hosted git repository. machristie pushed a commit to branch ansible-haproxy in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 8a30c61ee5c19076c92e243d536159622ccc4a24 Author: Marcus Christie <[email protected]> AuthorDate: Mon Jun 5 17:19:35 2023 -0400 Ansible: add ssl certificate generation and HAProxy for api server --- dev-tools/ansible/airavata.yml | 1 + dev-tools/ansible/apiserver.yml | 1 + .../scigap/develop/group_vars/all/vars.yml | 4 ++ dev-tools/ansible/roles/api-orch/defaults/main.yml | 5 ++ .../files/prepareLetsEncryptCertificates.sh | 13 ++++ .../api-orch/handlers/main.yml} | 20 +----- .../tasks/haproxy/install_deps_Centos_7.yml} | 18 ++---- .../tasks/haproxy/install_deps_Rocky_8.yml} | 22 +++---- dev-tools/ansible/roles/api-orch/tasks/main.yml | 58 +++++++++++++++++ .../roles/api-orch/templates/haproxy.cfg.j2 | 75 ++++++++++++++++++++++ 10 files changed, 172 insertions(+), 45 deletions(-) diff --git a/dev-tools/ansible/airavata.yml b/dev-tools/ansible/airavata.yml index 5969528aca..cc5566424d 100644 --- a/dev-tools/ansible/airavata.yml +++ b/dev-tools/ansible/airavata.yml @@ -43,6 +43,7 @@ - role: common become: yes become_user: "{{user}}" + - letsencrypt - role: api-orch become: yes become_user: "{{user}}" diff --git a/dev-tools/ansible/apiserver.yml b/dev-tools/ansible/apiserver.yml index 8a22961462..505d73ae8c 100644 --- a/dev-tools/ansible/apiserver.yml +++ b/dev-tools/ansible/apiserver.yml @@ -31,6 +31,7 @@ - role: common become: yes become_user: "{{user}}" + - letsencrypt - role: api-orch become: yes become_user: "{{user}}" diff --git a/dev-tools/ansible/inventories/scigap/develop/group_vars/all/vars.yml b/dev-tools/ansible/inventories/scigap/develop/group_vars/all/vars.yml index 5f1a36c285..209af79afc 100644 --- a/dev-tools/ansible/inventories/scigap/develop/group_vars/all/vars.yml +++ b/dev-tools/ansible/inventories/scigap/develop/group_vars/all/vars.yml @@ -71,6 +71,7 @@ zookeeper_connection_url: "{{ groups['zookeeper'][0] }}:{{ zookeeper_client_port api_server_name: "apiserver-node0" api_server_host: "{{ groups['api-orch'][0] }}" api_server_port: "8930" +api_server_public_hostname: "apidev.scigap.org" api_secured: "true" tls_enable: "true" api_server_tls_port: "9930" @@ -146,6 +147,9 @@ keycloak_master_account_username: "admin" keycloak_master_account_password: "{{ vault_keycloak_master_account_password }}" keycloak_vhost_servername: "iamdev.scigap.org" +# Letsencrypt +letsencrypt_email: "[email protected]" + # Helix helix_version: 0.9.9 helix_url: https://downloads.apache.org/helix/{{helix_version}}/binaries/helix-core-{{helix_version}}-pkg.tar diff --git a/dev-tools/ansible/roles/api-orch/defaults/main.yml b/dev-tools/ansible/roles/api-orch/defaults/main.yml index e1c0476ec7..1c7c2f9a28 100644 --- a/dev-tools/ansible/roles/api-orch/defaults/main.yml +++ b/dev-tools/ansible/roles/api-orch/defaults/main.yml @@ -47,3 +47,8 @@ api_orch_systemd_unit_file: "/etc/systemd/system/apiorch.service" thrift_client_pool_abandoned_removal_enabled: false thrift_client_pool_abandoned_removal_logged: false + +api_server_public_hostname: "localhost" +haproxy_conf_destination: "/etc/haproxy/haproxy.cfg" +haproxy_api_server_ssl_cert: "/etc/ssl/{{ api_server_public_hostname }}/{{ api_server_public_hostname }}.pem" +api_server_letsencrypt_ssl_cert: "/etc/letsencrypt/live/{{ api_server_public_hostname }}/cert.pem" diff --git a/dev-tools/ansible/roles/api-orch/files/prepareLetsEncryptCertificates.sh b/dev-tools/ansible/roles/api-orch/files/prepareLetsEncryptCertificates.sh new file mode 100644 index 0000000000..ba99e0ac7d --- /dev/null +++ b/dev-tools/ansible/roles/api-orch/files/prepareLetsEncryptCertificates.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +umask 077 + +# Loop through all Let's Encrypt certificates +for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do + + CERTIFICATE=`basename $CERTIFICATE` + + # Combine certificate and private key to single file + cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/ssl/$CERTIFICATE/$CERTIFICATE.pem + +done diff --git a/dev-tools/ansible/apiserver.yml b/dev-tools/ansible/roles/api-orch/handlers/main.yml similarity index 71% copy from dev-tools/ansible/apiserver.yml copy to dev-tools/ansible/roles/api-orch/handlers/main.yml index 8a22961462..5ab12f6a36 100644 --- a/dev-tools/ansible/apiserver.yml +++ b/dev-tools/ansible/roles/api-orch/handlers/main.yml @@ -19,20 +19,6 @@ # --- -# Just gather facts on database to get internal IP address -- hosts: database - gather_facts: True - -- hosts: api-orch - tags: api-orch, airavata - roles: - - env_setup - - java - - role: common - become: yes - become_user: "{{user}}" - - role: api-orch - become: yes - become_user: "{{user}}" - -... +- name: restart haproxy + service: name=haproxy state=reloaded enabled=yes + become: yes diff --git a/dev-tools/ansible/apiserver.yml b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml similarity index 71% copy from dev-tools/ansible/apiserver.yml copy to dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml index 8a22961462..ee115be015 100644 --- a/dev-tools/ansible/apiserver.yml +++ b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml @@ -19,20 +19,10 @@ # --- -# Just gather facts on database to get internal IP address -- hosts: database - gather_facts: True -- hosts: api-orch - tags: api-orch, airavata - roles: - - env_setup - - java - - role: common - become: yes - become_user: "{{user}}" - - role: api-orch - become: yes - become_user: "{{user}}" +- name: yum install haproxy18 (Centos 7) + yum: name=haproxy18 state=present + become: true + ... diff --git a/dev-tools/ansible/apiserver.yml b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml similarity index 71% copy from dev-tools/ansible/apiserver.yml copy to dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml index 8a22961462..8d48c477fe 100644 --- a/dev-tools/ansible/apiserver.yml +++ b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml @@ -19,20 +19,14 @@ # --- -# Just gather facts on database to get internal IP address -- hosts: database - gather_facts: True -- hosts: api-orch - tags: api-orch, airavata - roles: - - env_setup - - java - - role: common - become: yes - become_user: "{{user}}" - - role: api-orch - become: yes - become_user: "{{user}}" +- name: dnf install haproxy (Rocky 8) + dnf: name={{ package }} state=latest + loop: + - haproxy + loop_control: + loop_var: package + become: true + become_user: root ... diff --git a/dev-tools/ansible/roles/api-orch/tasks/main.yml b/dev-tools/ansible/roles/api-orch/tasks/main.yml index f121fcb20e..19f1cb3919 100644 --- a/dev-tools/ansible/roles/api-orch/tasks/main.yml +++ b/dev-tools/ansible/roles/api-orch/tasks/main.yml @@ -82,6 +82,64 @@ owner={{ user }} group={{ group }} +# Create a SSL certificate for the api server + +- name: allow http for Let's Encrypt certificate renewal + firewalld: + zone: public + permanent: yes + state: enabled + immediate: yes + service: http + become_user: root + +- name: copy prepareLetsEncryptCertificates.sh script + copy: + src: prepareLetsEncryptCertificates.sh + dest: "/etc/haproxy/" + mode: 755 + become_user: root + +# - name: copy cron job to renew certificates +# copy: +# src: renewLetsEncryptCertificates.sh +# dest: /etc/cron.monthly/ +# mode: 0755 +# become_user: root + +- name: check if SSL certificate exists + stat: + path: "{{ api_server_letsencrypt_ssl_cert }}" + register: stat_api_server_ssl_cert_result + become: yes + +- name: generate certificate if it doesn't exist + command: certbot --standalone --non-interactive --agree-tos --email "{{ letsencrypt_email }}" -d {{ api_server_public_hostname }} certonly + become: yes + when: not stat_api_server_ssl_cert_result.stat.exists + +- name: set certificate renewal post-hook + command: certbot renew --installer null --standalone --post-hook "/etc/haproxy/prepareLetsEncryptCertificates.sh && systemctl reload haproxy.service" --quiet + become: yes + +# Use HAProxy to proxy SSL port to non-SSL port + +- name: Install HAProxy + include_tasks: install_deps_{{ ansible_distribution }}_{{ ansible_distribution_major_version }}.yml + +- name: Copy HAProxy config file + template: src=haproxy.cfg.j2 + dest={{ haproxy_conf_destination }} + backup=true + become_user: root + notify: + - restart haproxy + +- name: start haproxy + service: name=haproxy state=started enabled=yes daemon_reload=yes + become: true + become_user: root + - name: allow only selected networks to access Airavata Sharing Registry firewalld: zone: public diff --git a/dev-tools/ansible/roles/api-orch/templates/haproxy.cfg.j2 b/dev-tools/ansible/roles/api-orch/templates/haproxy.cfg.j2 new file mode 100644 index 0000000000..b3b5d8133d --- /dev/null +++ b/dev-tools/ansible/roles/api-orch/templates/haproxy.cfg.j2 @@ -0,0 +1,75 @@ +#--------------------------------------------------------------------- +# Example configuration for a possible web application. See the +# full configuration options online. +# +# https://www.haproxy.org/download/1.8/doc/configuration.txt +# +#--------------------------------------------------------------------- + +#--------------------------------------------------------------------- +# Global settings +#--------------------------------------------------------------------- +global + # to have these messages end up in /var/log/haproxy.log you will + # need to: + # + # 1) configure syslog to accept network log events. This is done + # by adding the '-r' option to the SYSLOGD_OPTIONS in + # /etc/sysconfig/syslog + # + # 2) configure local2 events to go to the /var/log/haproxy.log + # file. A line like the following can be added to + # /etc/sysconfig/syslog + # + # local2.* /var/log/haproxy.log + # + log 127.0.0.1 local2 + + chroot /var/lib/haproxy + pidfile /var/run/haproxy.pid + maxconn 4000 + user haproxy + group haproxy + daemon + + # turn on stats unix socket + stats socket /var/lib/haproxy/stats + + # utilize system-wide crypto-policies + ssl-default-bind-ciphers PROFILE=SYSTEM + ssl-default-server-ciphers PROFILE=SYSTEM + +#--------------------------------------------------------------------- +# common defaults that all the 'listen' and 'backend' sections will +# use if not designated in their block +#--------------------------------------------------------------------- +defaults + log global + option httplog + option dontlognull + option http-server-close + option forwardfor except 127.0.0.0/8 + option redispatch + +#--------------------------------------------------------------------- +# main frontend which proxys to the backends +#--------------------------------------------------------------------- +frontend main + mode tcp + log global + option tcplog + bind *:{{ api_server_tls_port }} ssl crt {{ haproxy_api_server_ssl_cert }} + default_backend fix-backend + +#--------------------------------------------------------------------- +# static backend for serving up images, stylesheets and such +#--------------------------------------------------------------------- + +#--------------------------------------------------------------------- +# round robin balancing between the various backends +#--------------------------------------------------------------------- +backend fix-backend + mode tcp + log global + option tcplog + server quickfix {{ airavata_api_host }}:{{ api_server_port }} check
