From b1bfee423b3bb9c7deab61e63bc5a80df7a023e2 Mon Sep 17 00:00:00 2001
From: Ian Wienand <iwienand@redhat.com>
Date: Fri, 6 Mar 2020 12:08:09 +1100
Subject: [PATCH] nodepool-builder: Add webserver

This adds the webserver that serves the logs and generated images.

Change-Id: I230f5291e0bd928af2e00966d76c3f385b749cb6
---
 .zuul.yaml                                    |  1 +
 inventory/groups.yaml                         |  5 +-
 .../handlers/main.yaml                        |  3 +
 .../roles/nodepool-builder/handlers/main.yaml |  4 ++
 .../roles/nodepool-builder/tasks/main.yaml    |  3 +
 .../nodepool-builder/tasks/webserver.yaml     | 33 ++++++++++
 .../nodepool-builder/templates/vhost.conf.j2  | 61 +++++++++++++++++++
 .../host_vars/nb01-test.opendev.org.yaml.j2   |  4 ++
 testinfra/test_nodepool.py                    | 12 ++++
 9 files changed, 124 insertions(+), 2 deletions(-)
 create mode 100644 playbooks/roles/nodepool-builder/handlers/main.yaml
 create mode 100644 playbooks/roles/nodepool-builder/tasks/webserver.yaml
 create mode 100644 playbooks/roles/nodepool-builder/templates/vhost.conf.j2

diff --git a/.zuul.yaml b/.zuul.yaml
index 1576f7fe20..c8394935d8 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -841,6 +841,7 @@
           label: ubuntu-bionic
     vars:
       run_playbooks:
+        - playbooks/service-letsencrypt.yaml
         - playbooks/service-nodepool.yaml
         - playbooks/remote_puppet_else.yaml
     files:
diff --git a/inventory/groups.yaml b/inventory/groups.yaml
index c88e069551..bd05bc8185 100644
--- a/inventory/groups.yaml
+++ b/inventory/groups.yaml
@@ -65,15 +65,16 @@ groups:
   kubernetes:
     - opendev-k8s*.opendev.org
   letsencrypt:
+    - files[0-9]*.open*.org
+    - gitea[0-9]*.opendev.org
     - graphite01.opendev.org
     - insecure-ci-registry[0-9]*.opendev.org
     - mirror[0-9]*.opendev.org
-    - files[0-9]*.open*.org
+    - nb[0-9]*.opendev.org
     - review-dev[0-9]*.open*.org
     - review[0-9]*.open*.org
     - static.openstack.org
     - static[0-9]*.opendev.org
-    - gitea[0-9]*.opendev.org
     - zuul[0-9]*.open*.org
   logstash:
     - logstash[0-9]*.open*.org
diff --git a/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml b/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml
index c451b5c4f8..d346633670 100644
--- a/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml
+++ b/playbooks/roles/letsencrypt-create-certs/handlers/main.yaml
@@ -171,6 +171,9 @@
 - name: letsencrypt updated gitea99-main
   include_tasks: roles/letsencrypt-create-certs/handlers/restart_gitea.yaml
 
+- name: letsencrypt updated nb01-test-main
+  include_tasks: roles/letsencrypt-create-certs/handlers/restart_apache.yaml
+
 # We split out handlers for each gitea host as handlers should be run in order
 # This allows us to do a rolling restart of the gitea backends.
 - name: letsencrypt updated gitea01-main
diff --git a/playbooks/roles/nodepool-builder/handlers/main.yaml b/playbooks/roles/nodepool-builder/handlers/main.yaml
new file mode 100644
index 0000000000..a7ec2ee0a4
--- /dev/null
+++ b/playbooks/roles/nodepool-builder/handlers/main.yaml
@@ -0,0 +1,4 @@
+- name: restart apache2
+  service:
+    name: apache2
+    state: restarted
diff --git a/playbooks/roles/nodepool-builder/tasks/main.yaml b/playbooks/roles/nodepool-builder/tasks/main.yaml
index 30d867387e..185d99f2ba 100644
--- a/playbooks/roles/nodepool-builder/tasks/main.yaml
+++ b/playbooks/roles/nodepool-builder/tasks/main.yaml
@@ -10,6 +10,9 @@
     - '/opt/nodepool_dib'
     - '/var/log/nodepool/builds'
 
+- name: Setup webserver
+  include_tasks: webserver.yaml
+
 - name: Ensure /etc/nodepool-builder-compose directory
   file:
     state: directory
diff --git a/playbooks/roles/nodepool-builder/tasks/webserver.yaml b/playbooks/roles/nodepool-builder/tasks/webserver.yaml
new file mode 100644
index 0000000000..13d2eb5899
--- /dev/null
+++ b/playbooks/roles/nodepool-builder/tasks/webserver.yaml
@@ -0,0 +1,33 @@
+- name: Install Apache
+  package:
+    name:
+      - apache2
+      - apache2-utils
+    state: present
+
+- name: Apache 2 ssl module
+  apache2_module:
+    state: present
+    name: ssl
+
+- name: Rewrite module
+  apache2_module:
+    state: present
+    name: rewrite
+
+- name: Create virtualhost
+  template:
+    src: vhost.conf.j2
+    dest: /etc/apache2/sites-available/001-nb.conf
+
+- name: Disable default site
+  command: a2dissite 000-default.conf
+  args:
+    removes: /etc/apache2/sites-enabled/000-default.conf
+
+- name: Enable mirror virtual host
+  command: a2ensite 001-nb
+  args:
+    creates: /etc/apache2/sites-enabled/001-nb.conf
+  notify:
+    - restart apache2
diff --git a/playbooks/roles/nodepool-builder/templates/vhost.conf.j2 b/playbooks/roles/nodepool-builder/templates/vhost.conf.j2
new file mode 100644
index 0000000000..e7e546747d
--- /dev/null
+++ b/playbooks/roles/nodepool-builder/templates/vhost.conf.j2
@@ -0,0 +1,61 @@
+<VirtualHost *:80>
+  ServerName {{ inventory_hostname }}
+
+  ErrorLog /var/log/apache2/nodepool_error.log
+  LogLevel warn
+  CustomLog /var/log/apache2/nodepool_access.log combined
+  ServerSignature Off
+
+  Redirect / https://{{ inventory_hostname }}/
+
+</VirtualHost>
+
+
+<VirtualHost *:443>
+  ServerName nb01.openstack.org
+
+  SSLEngine on
+
+  SSLCertificateFile      /etc/letsencrypt-certs/{{ inventory_hostname }}/{{ inventory_hostname }}.cer
+  SSLCertificateKeyFile   /etc/letsencrypt-certs/{{ inventory_hostname }}/{{ inventory_hostname }}.key
+  SSLCertificateChainFile /etc/letsencrypt-certs/{{ inventory_hostname }}/ca.cer
+
+  SSLProtocol All -SSLv2 -SSLv3
+  # Note: this list should ensure ciphers that provide forward secrecy
+  SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!AES256:!aNULL:!eNULL:!MD5:!DSS:!PSK:!SRP
+  SSLHonorCipherOrder on
+
+  DocumentRoot /var/log/nodepool/builds
+  <Directory /var/log/nodepool/builds>
+    Options Indexes FollowSymLinks MultiViews
+    AllowOverride None
+    Require all granted
+  </Directory>
+
+  # Allow access to image files
+  Alias /images /opt/nodepool_dib
+  <Directory /opt/nodepool_dib>
+    Options Indexes FollowSymLinks MultiViews
+    AllowOverride None
+    Require all granted
+    # Only allow access to the qcow2 files as they are smallest
+    <FilesMatch ".+\.(vhd|raw)(\.(md5|sha256))?$">
+      Require all denied
+    </FilesMatch>
+  </Directory>
+  # Exclude the dib build dir as well.
+  <Directory /opt/nodepool_dib/*.d/>
+    Require all denied
+  </Directory>
+
+  AddType text/plain .log
+  <IfModule mod_deflate.c>
+      SetOutputFilter DEFLATE
+  </IfModule>
+
+  ErrorLog /var/log/apache2/nodepool_error.log
+  LogLevel warn
+  CustomLog /var/log/apache2/nodepool_access.log combined
+  ServerSignature Off
+
+</VirtualHost>
\ No newline at end of file
diff --git a/playbooks/zuul/templates/host_vars/nb01-test.opendev.org.yaml.j2 b/playbooks/zuul/templates/host_vars/nb01-test.opendev.org.yaml.j2
index d2799c226a..02614e7724 100644
--- a/playbooks/zuul/templates/host_vars/nb01-test.opendev.org.yaml.j2
+++ b/playbooks/zuul/templates/host_vars/nb01-test.opendev.org.yaml.j2
@@ -1 +1,5 @@
+letsencrypt_certs:
+  nb01-test-main:
+    - nb01-test.opendev.org
+
 nodepool_base_install_zookeeper: True
\ No newline at end of file
diff --git a/testinfra/test_nodepool.py b/testinfra/test_nodepool.py
index a5e262d181..d591748ab2 100644
--- a/testinfra/test_nodepool.py
+++ b/testinfra/test_nodepool.py
@@ -38,3 +38,15 @@ def test_builder_container_running(host):
 
     cmd = host.run("podman ps -a --format '{{ .Names }}'")
     assert 'nodepool-builder-compose_nodepool-builder_1' in cmd.stdout
+
+def test_builder_webserver_running(host):
+    if host.backend.get_hostname() != 'nb01-test.opendev.org':
+        pytest.skip()
+
+    apache = host.service('apache2')
+    assert apache.is_running
+
+    cmd = host.run('curl --insecure '
+                   '--resolve nb01-test.opendev.org:443:127.0.0.1 '
+                   'https://nb01-test.opendev.org/')
+    assert 'Index of /' in cmd.stdout