diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2023-12-20 10:36:25 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2024-02-10 22:59:43 +0100 |
| commit | f331a667d3827c5c7603c87956c601d5e42ef82b (patch) | |
| tree | 13b7c011a87991654c56fa785a734f5c21ff86d3 /gnu/build | |
| parent | 11d5b505e5e0f6bccd804d407cc609b421962073 (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/build')
| -rw-r--r-- | gnu/build/secret-service.scm | 62 |
1 files changed, 40 insertions, 22 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 |
| 100 | local PORT. If connect fails, sleep 1s and retry RETRY times; once connected, | 115 | at ADDRESS, an address as returned by 'make-socket-address'. If connection |
| 101 | wait for at most HANDSHAKE-TIMEOUT seconds for handshake to complete. Return | 116 | fails, sleep 1s and retry RETRY times; once connected, wait for at most |
| 102 | #f on failure." | 117 | HANDSHAKE-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 |
| 173 | Write them to the file system. Return the list of files installed on success, | 190 | for a secret service client to send secrets. Write them to the file system. |
| 174 | and #f otherwise." | 191 | Return 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)) |
