summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2023-12-20 10:36:25 +0100
committerLudovic Courtès <ludo@gnu.org>2024-02-10 22:59:43 +0100
commitf331a667d3827c5c7603c87956c601d5e42ef82b (patch)
tree13b7c011a87991654c56fa785a734f5c21ff86d3 /gnu
parent11d5b505e5e0f6bccd804d407cc609b421962073 (diff)
services: secret-service: Make the endpoint configurable.
Until now, the secret service had a hard-coded TCP endpoint on port 1004. This change lets users specify arbitrary socket addresses. * gnu/build/secret-service.scm (socket-address->string): New procedure, taken from Shepherd. (secret-service-send-secrets): Replace ‘port’ by ‘address’ and adjust accordingly. (secret-service-receive-secrets): Likewise. * gnu/services/virtualization.scm (secret-service-shepherd-services): Likewise. (secret-service-operating-system): Add optional ‘address’ parameter and honor it. Adjust ‘start’ method accordingly. Change-Id: I87a9514f1c170dca756ce76083d7182c6ebf6578
Diffstat (limited to 'gnu')
-rw-r--r--gnu/build/secret-service.scm62
-rw-r--r--gnu/services/virtualization.scm40
2 files changed, 63 insertions, 39 deletions
diff --git a/gnu/build/secret-service.scm b/gnu/build/secret-service.scm
index e13fd4eef3a..0226c640329 100644
--- a/gnu/build/secret-service.scm
+++ b/gnu/build/secret-service.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2020-2022 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2020-2023 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org> 3;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
4;;; 4;;;
5;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
@@ -93,13 +93,28 @@ Return #t in the former case and #f in the latter case."
93 ('readable #t) 93 ('readable #t)
94 ('timeout #f))))))) 94 ('timeout #f)))))))
95 95
96(define* (secret-service-send-secrets port secret-root 96(define (socket-address->string address)
97 "Return a human-readable representation of ADDRESS, an object as returned by
98'make-socket-address'."
99 (let ((family (sockaddr:fam address)))
100 (cond ((= AF_INET family)
101 (string-append (inet-ntop AF_INET (sockaddr:addr address))
102 ":" (number->string (sockaddr:port address))))
103 ((= AF_INET6 family)
104 (string-append "[" (inet-ntop AF_INET6 (sockaddr:addr address)) "]"
105 ":" (number->string (sockaddr:port address))))
106 ((= AF_UNIX family)
107 (sockaddr:path address))
108 (else
109 (object->string address)))))
110
111(define* (secret-service-send-secrets address secret-root
97 #:key (retry 60) 112 #:key (retry 60)
98 (handshake-timeout 180)) 113 (handshake-timeout 180))
99 "Copy all files under SECRET-ROOT using TCP to secret-service listening at 114 "Copy all files under SECRET-ROOT by connecting to secret-service listening
100local PORT. If connect fails, sleep 1s and retry RETRY times; once connected, 115at ADDRESS, an address as returned by 'make-socket-address'. If connection
101wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return 116fails, sleep 1s and retry RETRY times; once connected, wait for at most
102#f on failure." 117HANDSHAKE-TIMEOUT seconds for handshake to complete. Return #f on failure."
103 (define (file->file+size+mode file-name) 118 (define (file->file+size+mode file-name)
104 (let ((stat (stat file-name)) 119 (let ((stat (stat file-name))
105 (target (substring file-name (string-length secret-root)))) 120 (target (substring file-name (string-length secret-root))))
@@ -118,9 +133,9 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
118 (dump-port input sock)))) 133 (dump-port input sock))))
119 files))) 134 files)))
120 135
121 (log "sending secrets to ~a~%" port) 136 (log "sending secrets to ~a~%" (socket-address->string address))
137
122 (let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0)) 138 (let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0))
123 (addr (make-socket-address AF_INET INADDR_LOOPBACK port))
124 (sleep (if (resolve-module '(fibers) #f) 139 (sleep (if (resolve-module '(fibers) #f)
125 (module-ref (resolve-interface '(fibers)) 'sleep) 140 (module-ref (resolve-interface '(fibers)) 'sleep)
126 sleep))) 141 sleep)))
@@ -129,7 +144,7 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
129 ;; forward port inside the guest. 144 ;; forward port inside the guest.
130 (let loop ((retry retry)) 145 (let loop ((retry retry))
131 (catch 'system-error 146 (catch 'system-error
132 (cute connect sock addr) 147 (cute connect sock address)
133 (lambda (key . args) 148 (lambda (key . args)
134 (when (zero? retry) 149 (when (zero? retry)
135 (apply throw key args)) 150 (apply throw key args))
@@ -147,7 +162,8 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
147 (('secret-service-server ('version version ...)) 162 (('secret-service-server ('version version ...))
148 (log "sending files from ~s...~%" secret-root) 163 (log "sending files from ~s...~%" secret-root)
149 (send-files sock) 164 (send-files sock)
150 (log "done sending files to port ~a~%" port) 165 (log "done sending files to ~a~%"
166 (socket-address->string address))
151 (close-port sock) 167 (close-port sock)
152 secret-root) 168 secret-root)
153 (x 169 (x
@@ -155,7 +171,8 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
155 (close-port sock) 171 (close-port sock)
156 #f)) 172 #f))
157 (begin ;timeout 173 (begin ;timeout
158 (log "timeout while sending files to ~a~%" port) 174 (log "timeout while sending files to ~a~%"
175 (socket-address->string address))
159 (close-port sock) 176 (close-port sock)
160 #f)))) 177 #f))))
161 178
@@ -168,19 +185,20 @@ wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return
168 (unless (= ENOENT (system-error-errno args)) 185 (unless (= ENOENT (system-error-errno args))
169 (apply throw args))))) 186 (apply throw args)))))
170 187
171(define (secret-service-receive-secrets port) 188(define (secret-service-receive-secrets address)
172 "Listen to local PORT and wait for a secret service client to send secrets. 189 "Listen to ADDRESS, an address returned by 'make-socket-address', and wait
173Write them to the file system. Return the list of files installed on success, 190for a secret service client to send secrets. Write them to the file system.
174and #f otherwise." 191Return the list of files installed on success, and #f otherwise."
175 192
176 (define (wait-for-client port) 193 (define (wait-for-client address)
177 ;; Wait for a TCP connection on PORT. Note: We cannot use the 194 ;; Wait for a connection on ADDRESS. Note: virtio-serial ports are safer
178 ;; virtio-serial ports, which would be safer, because they are 195 ;; than TCP connections but they are (presumably) unsupported on GNU/Hurd.
179 ;; (presumably) unsupported on GNU/Hurd.
180 (let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0))) 196 (let ((sock (socket AF_INET (logior SOCK_CLOEXEC SOCK_STREAM) 0)))
181 (bind sock AF_INET INADDR_ANY port) 197 (bind sock address)
182 (listen sock 1) 198 (listen sock 1)
183 (log "waiting for secrets on port ~a...~%" port) 199 (log "waiting for secrets on ~a...~%"
200 (socket-address->string address))
201
184 (match (select (list sock) '() '() 60) 202 (match (select (list sock) '() '() 60)
185 (((_) () ()) 203 (((_) () ())
186 (match (accept sock) 204 (match (accept sock)
@@ -244,7 +262,7 @@ and #f otherwise."
244 (log "invalid secrets received~%") 262 (log "invalid secrets received~%")
245 #f))) 263 #f)))
246 264
247 (let* ((port (wait-for-client port)) 265 (let* ((port (wait-for-client address))
248 (result (and=> port read-secrets))) 266 (result (and=> port read-secrets)))
249 (when port 267 (when port
250 (close-port port)) 268 (close-port port))
diff --git a/gnu/services/virtualization.scm b/gnu/services/virtualization.scm
index f0f0ab3bf11..5b8566f6009 100644
--- a/gnu/services/virtualization.scm
+++ b/gnu/services/virtualization.scm
@@ -996,7 +996,7 @@ specified, the QEMU default path is used."))
996;;; Secrets for guest VMs. 996;;; Secrets for guest VMs.
997;;; 997;;;
998 998
999(define (secret-service-shepherd-services port) 999(define (secret-service-shepherd-services address)
1000 "Return a Shepherd service that fetches sensitive material at local PORT, 1000 "Return a Shepherd service that fetches sensitive material at local PORT,
1001over TCP. Reboot upon failure." 1001over TCP. Reboot upon failure."
1002 ;; This is a Shepherd service, rather than an activation snippet, to make 1002 ;; This is a Shepherd service, rather than an activation snippet, to make
@@ -1018,7 +1018,7 @@ over TCP. Reboot upon failure."
1018 "receiving secrets from the host...~%") 1018 "receiving secrets from the host...~%")
1019 (force-output (current-error-port)) 1019 (force-output (current-error-port))
1020 1020
1021 (let ((sent (secret-service-receive-secrets #$port))) 1021 (let ((sent (secret-service-receive-secrets #$address)))
1022 (unless sent 1022 (unless sent
1023 (sleep 3) 1023 (sleep 3)
1024 (reboot)))))) 1024 (reboot))))))
@@ -1039,9 +1039,13 @@ over TCP. Reboot upon failure."
1039boot time. This service is meant to be used by virtual machines (VMs) that 1039boot time. This service is meant to be used by virtual machines (VMs) that
1040can only be accessed by their host."))) 1040can only be accessed by their host.")))
1041 1041
1042(define (secret-service-operating-system os) 1042(define* (secret-service-operating-system os
1043 #:optional
1044 (address
1045 #~(make-socket-address
1046 AF_INET INADDR_ANY 1004)))
1043 "Return an operating system based on OS that includes the secret-service, 1047 "Return an operating system based on OS that includes the secret-service,
1044that will be listening to receive secret keys on port 1004, TCP." 1048that will be listening to receive secret keys on ADDRESS."
1045 (operating-system 1049 (operating-system
1046 (inherit os) 1050 (inherit os)
1047 (services 1051 (services
@@ -1049,7 +1053,7 @@ that will be listening to receive secret keys on port 1004, TCP."
1049 ;; activation: that requires entropy and thus takes time during boot, and 1053 ;; activation: that requires entropy and thus takes time during boot, and
1050 ;; those keys are going to be overwritten by secrets received from the 1054 ;; those keys are going to be overwritten by secrets received from the
1051 ;; host anyway. 1055 ;; host anyway.
1052 (cons (service secret-service-type 1004) 1056 (cons (service secret-service-type address)
1053 (modify-services (operating-system-user-services os) 1057 (modify-services (operating-system-user-services os)
1054 (openssh-service-type 1058 (openssh-service-type
1055 config => (openssh-configuration 1059 config => (openssh-configuration
@@ -1243,24 +1247,26 @@ is added to the OS specified in CONFIG."
1243 (source-module-closure '((gnu build secret-service) 1247 (source-module-closure '((gnu build secret-service)
1244 (guix build utils))) 1248 (guix build utils)))
1245 #~(lambda () 1249 #~(lambda ()
1246 (let ((pid (fork+exec-command #$vm-command 1250 (let* ((pid (fork+exec-command #$vm-command
1247 #:user "childhurd" 1251 #:user "childhurd"
1248 ;; XXX TODO: use "childhurd" after 1252 ;; XXX TODO: use "childhurd" after
1249 ;; updating Shepherd 1253 ;; updating Shepherd
1250 #:group "kvm" 1254 #:group "kvm"
1251 #:environment-variables 1255 #:environment-variables
1252 ;; QEMU tries to write to /var/tmp 1256 ;; QEMU tries to write to /var/tmp
1253 ;; by default. 1257 ;; by default.
1254 '("TMPDIR=/tmp"))) 1258 '("TMPDIR=/tmp")))
1255 (port #$(hurd-vm-port config %hurd-vm-secrets-port)) 1259 (port #$(hurd-vm-port config %hurd-vm-secrets-port))
1256 (root #$(hurd-vm-configuration-secret-root config))) 1260 (root #$(hurd-vm-configuration-secret-root config))
1261 (address (make-socket-address AF_INET INADDR_LOOPBACK
1262 port)))
1257 (catch #t 1263 (catch #t
1258 (lambda _ 1264 (lambda _
1259 ;; XXX: 'secret-service-send-secrets' won't complete until 1265 ;; XXX: 'secret-service-send-secrets' won't complete until
1260 ;; the guest has booted and its secret service server is 1266 ;; the guest has booted and its secret service server is
1261 ;; running, which could take 20+ seconds during which PID 1 1267 ;; running, which could take 20+ seconds during which PID 1
1262 ;; is stuck waiting. 1268 ;; is stuck waiting.
1263 (if (secret-service-send-secrets port root) 1269 (if (secret-service-send-secrets address root)
1264 pid 1270 pid
1265 (begin 1271 (begin
1266 (kill (- pid) SIGTERM) 1272 (kill (- pid) SIGTERM)