Merge branch 'ansible-haproxy' into develop
diff --git a/dev-tools/ansible/airavata.yml b/dev-tools/ansible/airavata.yml
index 5969528..cc55664 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 8a22961..505d73a 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 97a388a..4d88f8b 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 @@
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"
diff --git a/dev-tools/ansible/roles/api-orch/defaults/main.yml b/dev-tools/ansible/roles/api-orch/defaults/main.yml
index e1c0476..1c7c2f9 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 @@
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 0000000..ba99e0a
--- /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/roles/api-orch/handlers/main.yml b/dev-tools/ansible/roles/api-orch/handlers/main.yml
new file mode 100644
index 0000000..5ab12f6
--- /dev/null
+++ b/dev-tools/ansible/roles/api-orch/handlers/main.yml
@@ -0,0 +1,24 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+- name: restart haproxy
+ service: name=haproxy state=reloaded enabled=yes
+ become: yes
diff --git a/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml
new file mode 100644
index 0000000..ee115be
--- /dev/null
+++ b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Centos_7.yml
@@ -0,0 +1,28 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+- name: yum install haproxy18 (Centos 7)
+ yum: name=haproxy18 state=present
+ become: true
+
+
+...
diff --git a/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml
new file mode 100644
index 0000000..8d48c47
--- /dev/null
+++ b/dev-tools/ansible/roles/api-orch/tasks/haproxy/install_deps_Rocky_8.yml
@@ -0,0 +1,32 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+
+- 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 f121fcb..19f1cb3 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 0000000..b3b5d81
--- /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