From 7c1501119b4218a283244fa6d5818a1147e4b977 Mon Sep 17 00:00:00 2001
From: Romain GARBAGE <romain.garbage@inria.fr>
Date: Wed, 19 Jun 2024 13:22:31 +0200
Subject: [PATCH] head-node: Add token filtering for Gitlab integration with
 Cuirass.

* head-node.scm (%nginx-gitlab-token): New variable.
(operating-system): Add service.
* nginx-config/nginx-locations.conf: New include directive and new filter.
---
 head-node.scm                     | 27 +++++++++++++++++++++++++++
 nginx-config/nginx-locations.conf |  9 +++++++++
 2 files changed, 36 insertions(+)

diff --git a/head-node.scm b/head-node.scm
index 2a82389..170cd4b 100644
--- a/head-node.scm
+++ b/head-node.scm
@@ -368,6 +368,32 @@ export CUIRASS_LOGGING_LEVEL=${CUIRASS_LOGGING_LEVEL:-debug}\n"
                                     "nginx-config/nginx-locations.conf")
                                  "nginx-locations.conf")))))
 
+(define %nginx-gitlab-token
+  ;; Create /etc/nginx-tokens with a random token if it doesn't exist.
+  (simple-service 'nginx-gitlab-token
+                  activation-service-type
+                  #~(begin
+                      (define file "/etc/nginx-tokens")
+                      (define (make-random-list n)
+                            (if (= n 0)
+                                '()
+                                (cons (integer->char
+                                       (+ (random 26) 97)) ;; ASCII code for a-z
+                                      (make-random-list (- n 1)))))
+                      ;; token is a random lowercase alphabetical
+                      ;; string containing 32 characters. This
+                      ;; corresponds to 1.90172e+45 different
+                      ;; combinations.
+                      (define token
+                        (list->string (make-random-list 32)))
+
+                      (unless (file-exists? file)
+                        (call-with-output-file file
+                          (lambda (port)
+                            (format port "set $GITLAB_TOKEN ~a;~%" token)
+                            ;; Ensure that the file is only readable by its owner.
+                            (chmod port #o600)))))))
+
 (define %nginx-mime-types
   ;; Provide /etc/nginx/mime.types (and a bunch of other files.)
   (simple-service 'nginx-mime.types
@@ -476,6 +502,7 @@ export CUIRASS_LOGGING_LEVEL=${CUIRASS_LOGGING_LEVEL:-debug}\n"
                            (file (file-append %nginx-config
                                               "/nginx.conf"))))
                  %nginx-mime-types
+                 %nginx-gitlab-token
 
                  (service certbot-service-type
                           (certbot-configuration
diff --git a/nginx-config/nginx-locations.conf b/nginx-config/nginx-locations.conf
index 760b2a7..17358c3 100644
--- a/nginx-config/nginx-locations.conf
+++ b/nginx-config/nginx-locations.conf
@@ -11,6 +11,15 @@ location = /nix-cache-info { proxy_pass http://localhost:3000; }
 
 # Cuirass.
 
+# The included file should define the variable $GITLAB_TOKEN using the
+# set directive: "set $GITLAB_TOKEN value;". It should be created
+# manually.
+include /etc/nginx-tokens;
+location ~ ^/admin/gitlab/event {
+    # Filter using Gitlab token
+    if ($http_x_gitlab_token != $GITLAB_TOKEN) { return 403; }
+    proxy_pass http://localhost:8081;
+}
 location ~ ^/admin {
     # Disallow access to unauthenticated clients.
     if ($ssl_client_verify != SUCCESS) { return 403; }
-- 
GitLab