From ff842b198969f662daa920333b5290e15b92f358 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johan=20Bj=C3=B6rklund?= <bjorklund@sunet.se>
Date: Thu, 14 Nov 2024 14:16:39 +0100
Subject: [PATCH] IntelMQ API.

---
 .../modules/soc/files/intelmq/api-config.json |  7 ++
 .../soc/files/intelmq/intelmq-api.service     | 23 ++++++
 .../soc/files/intelmq/intelmq-api.socket      |  9 +++
 .../puppet/modules/soc/manifests/intelmq.pp   | 53 ++++++++++++
 .../templates/intelmq/intelmq-vhost.conf.erb  | 80 +++++++++++++++++++
 5 files changed, 172 insertions(+)
 create mode 100644 global/overlay/etc/puppet/modules/soc/files/intelmq/api-config.json
 create mode 100644 global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.service
 create mode 100644 global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.socket
 create mode 100644 global/overlay/etc/puppet/modules/soc/templates/intelmq/intelmq-vhost.conf.erb

diff --git a/global/overlay/etc/puppet/modules/soc/files/intelmq/api-config.json b/global/overlay/etc/puppet/modules/soc/files/intelmq/api-config.json
new file mode 100644
index 0000000..435bdcb
--- /dev/null
+++ b/global/overlay/etc/puppet/modules/soc/files/intelmq/api-config.json
@@ -0,0 +1,7 @@
+{
+	"intelmq_ctl_cmd": ["sudo", "-u", "intelmq", "/opt/intelmq/venv/bin/intelmqctl"],
+	"allowed_path": "/opt/intelmq/var/lib/bots/",
+	"session_store": "/etc/intelmq/api-session.sqlite",
+	"session_duration": 86400,
+	"allow_origins": ["*"]
+}
diff --git a/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.service b/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.service
new file mode 100644
index 0000000..d1ef41c
--- /dev/null
+++ b/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.service
@@ -0,0 +1,23 @@
+[Unit]
+Description=Gunicorn deamon to serve the IntelMQ API
+Requires=intelmq-api.socket
+After=network.target
+
+[Service]
+
+# To override settings path, use e.g.:
+# Environment="INTELMQ_API_CONFIG=/etc/intelmq/api-config.json"
+
+Environment="ROOT_PATH=/intelmq"
+User=www-data
+Group=www-data
+RuntimeDirectory=gunicorn
+WorkingDirectory=/opt/intelmq/venv/lib/python3.11/site-packages/intelmq_api
+ExecStart=/opt/intelmq/venv/bin/gunicorn intelmq_api.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind unix:intelmq_api.sock --log-level DEBUG
+ExecReload=/bin/kill -s HUP $MAINPID
+KillMode=mixed
+TimeoutStopSec=5
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.socket b/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.socket
new file mode 100644
index 0000000..69bf331
--- /dev/null
+++ b/global/overlay/etc/puppet/modules/soc/files/intelmq/intelmq-api.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=The socket to handle IntelMQ API requests
+
+[Socket]
+ListenStream=/opt/intelmq/venv/lib/python3.11/site-packages/intelmq_api/intelmq_api.sock
+SocketUser=www-data
+
+[Install]
+WantedBy=sockets.target
diff --git a/global/overlay/etc/puppet/modules/soc/manifests/intelmq.pp b/global/overlay/etc/puppet/modules/soc/manifests/intelmq.pp
index 00441fd..29f93ca 100644
--- a/global/overlay/etc/puppet/modules/soc/manifests/intelmq.pp
+++ b/global/overlay/etc/puppet/modules/soc/manifests/intelmq.pp
@@ -1,5 +1,11 @@
 class soc::intelmq(
+  Optional[String]    $tls_cert   = undef,
+  Optional[String]    $tls_chain  = undef,
+  Optional[String]    $tls_key    = undef,
+  String              $servername = $::fact['networking.fqdn'],
+  Boolean             $use_snakeoil = false,
 ) {
+  include sunet::systemd_reload
 
   group { 'intelmq':
     ensure => present,
@@ -88,4 +94,51 @@ class soc::intelmq(
     notify  => Service['apache2'],
   }
 
+  file { '/etc/apache2/sites-available/intelmq-vhost.conf':
+    ensure   => file,
+    template => 'soc/intelmq/intelmq-vhost.conf.erb'
+  }
+
+  file { '/etc/intelmq/api-config.json':
+    ensure  => file,
+    owner   => 'intelmq',
+    group   => 'intelmq',
+    mode    => '0444'
+    content => 'soc/intelmq/api-config.json',
+  }
+
+  file { 'api-session.sqlite':
+    ensure  => 'present',
+    replace => 'no',
+    owner   => 'intelmq',
+    group   => 'www-data',
+    mode    => '0660'
+  }
+
+  file { '/etc/systemd/system/intelmq-api.service':
+    ensure  => file,
+    content => 'soc/intelmq/intelmq-api.service',
+    notify  => [Class['sunet:systemd_reload'], Service['intelmq-api.service'],],
+  }
+
+  file { '/etc/systemd/system/intelmq-api.socket':
+    ensure  => file,
+    content => 'soc/intelmq/intelmq-api.socket',
+    notify  => [Class['sunet:systemd_reload'], Service['intelmq-api.socket'],],
+  }
+
+  service { 'intelmq-api.service':
+    ensure     => running,
+    name       => 'intelmq-api.service',
+    enabled    => true,
+    hasrestart => true,
+  }
+
+  service { 'intelmq-api.socket':
+    ensure     => running,
+    name       => 'intelmq-api.socket',
+    enabled    => true,
+    hasrestart => true,
+  }
+
 }
diff --git a/global/overlay/etc/puppet/modules/soc/templates/intelmq/intelmq-vhost.conf.erb b/global/overlay/etc/puppet/modules/soc/templates/intelmq/intelmq-vhost.conf.erb
new file mode 100644
index 0000000..efe8a1d
--- /dev/null
+++ b/global/overlay/etc/puppet/modules/soc/templates/intelmq/intelmq-vhost.conf.erb
@@ -0,0 +1,80 @@
+<VirtualHost *:80>
+        ServerName <%= @servername %>
+        ServerAdmin cert@cert.sunet.se
+        DocumentRoot /var/www/html
+
+        RewriteEngine   On
+        RewriteRule     ^(.*)$          https://<%= @servername %>/$1     [R,L]
+
+        ErrorLog ${APACHE_LOG_DIR}/error.log
+        CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
+
+<VirtualHost *:443>
+        ServerName <%= @servername %>
+        ServerAdmin cert@cert.sunet.se
+
+        SSLEngine on
+        <% if @use_snakeoil -%>
+        SSLCertificateFile      /etc/letsencrypt/live/intelmq-test.cert.sunet.se/cert.pem
+        SSLCertificateKeyFile   /etc/letsencrypt/live/intelmq-test.cert.sunet.se/privkey.pem
+        <% else -%> 
+        SSLCertificateFile      <%= @tls_cert %>
+        SSLCertificateKeyFile   <%= @tls_key %>
+        SSLCertificateChainFile <%= @tls_chain %>
+        <% end -%>
+
+        SSLCACertificatePath /etc/ssl/certs/
+        SSLCACertificateFile /etc/ssl/certs/ca-certificates.crt
+
+        Protocols               h2 http/1.1
+        SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
+        SSLHonorCipherOrder     off
+        SSLSessionTickets       off
+        Header                  always set Strict-Transport-Security "max-age=63072000"
+
+        <IfModule mod_proxy.c>
+                ProxyRequests   Off
+                <Location "/api">
+                        ProxyPass               "http://127.0.0.1:8666/api"
+                        ProxyPassReverse        "http://127.0.0.1:8666/api"
+                        Header                  always set X-DEBUG-PATH "/api"
+                </Location>
+        </IfModule>
+
+#        RewriteEngine on
+#        RewriteCond %{REQUEST_URI} !^/(index.html|static|api|intelmq-webinput)
+#        RewriteRule .* /index.html [PT]
+
+        DocumentRoot /opt/intelmq/www-fody
+        <Directory /opt/intelmq/www-fody>
+            <IfModule mod_headers.c>
+                Header set Content-Security-Policy "script-src 'self'"
+                Header set X-Content-Security-Policy "script-src 'self'"
+            </IfModule>
+            Require all granted
+            Options FollowSymLinks
+        </Directory>
+
+        Alias /intelmq-manager /usr/share/intelmq_manager/html/
+        <Directory /usr/share/intelmq_manager/html>
+#                AuthType                Basic
+#                AuthName                "IntelMQ"
+#                AuthBasicProvider       file
+#                AuthUserFile            /etc/apache2/htpasswd
+#                Require                 user sunetcert
+
+            <IfModule mod_headers.c>
+                    Header set Content-Security-Policy "script-src 'self'"
+                    Header set X-Content-Security-Policy "script-src 'self'"
+            </IfModule>
+        </Directory>
+
+        <Location /intelmq/>
+                ProxyPass unix:/opt/intelmq/venv/lib/python3.11/site-packages/intelmq_api/intelmq_api.sock|http://127.0.0.1/
+                ProxyPassReverse unix:/opt/intelmq/venv/lib/python3.11/site-packages/intelmq_api/intelmq_api.sock|http://127.0.0.1/
+        </Location>
+
+        ErrorLog ${APACHE_LOG_DIR}/error.log
+        CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>