From 9043e23196ba28590ee272fb5f71f30a4ab73385 Mon Sep 17 00:00:00 2001 From: Saku Laesvuori Date: Thu, 20 Apr 2023 14:30:24 +0300 Subject: home: services: openssh: Add configuration option for jump proxies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new 'proxy' field to openssh-host to allow ProxyCommand or ProxyJump, but not both, to be configured. Configuring both would cause the serialization order to determine which one is used. Deprecate the 'proxy-command' field because the 'proxy' field replaces it. * gnu/home/services/ssh.scm (proxy-jump->string, proxy-command-or-jump-list?, serialize-proxy-command-or-jump-list, sanitize-proxy-command): New procedure. (proxy-jump, proxy-command): New record type. (openssh-host)[proxy-command]: Mark field as deprecated because OpenSSH can't have ProxyCommand and ProxyJump configured at the same time. * doc/guix.texi (Secure Shell): Update to match the changes to the service. Signed-off-by: Ludovic Courtès --- doc/guix.texi | 29 ++++++++++++++++++--- gnu/home/services/ssh.scm | 65 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 53035fd5e9..4190f37ad5 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -42630,10 +42630,31 @@ machine. @item @code{compression?} (default: @code{#f}) (type: boolean) Whether to compress data in transit. -@item @code{proxy-command} (type: maybe-string) -The command to use to connect to the server. As an example, a command -to connect via an HTTP proxy at 192.0.2.0 would be: @code{"nc -X connect --x 192.0.2.0:8080 %h %p"}. +@item @code{proxy} (type: maybe-proxy-command-or-jump-list) +The command to use to connect to the server or a list of SSH hosts to +jump through before connecting to the server. The field may be set to either a +@code{proxy-command} or a list of @code{proxy-jump} records. + +As an example, a @code{proxy-command} to connect via an HTTP proxy at 192.0.2.0 +would be constructed with: @code{(proxy-command "nc -X connect -x +192.0.2.0:8080 %h %p")}. + +@deftp {Data Type} proxy-jump +Available @code{proxy-jump} fields are: + +@table @asis +@item @code{user} (type: maybe-string) +User name on the remote host. + +@item @code{host-name} (type: string) +Host name---e.g., @code{foo.example.org} or @code{192.168.1.2}. + +@item @code{port} (type: maybe-natural-number) +TCP port number to connect to. + +@end table + +@end deftp @item @code{host-key-algorithms} (type: maybe-string-list) The list of accepted host key algorithms---e.g., diff --git a/gnu/home/services/ssh.scm b/gnu/home/services/ssh.scm index 01917a29cd..6aeb6ad5a7 100644 --- a/gnu/home/services/ssh.scm +++ b/gnu/home/services/ssh.scm @@ -20,6 +20,7 @@ (define-module (gnu home services ssh) #:use-module (guix gexp) #:use-module (guix records) + #:use-module (guix deprecation) #:use-module (guix diagnostics) #:use-module (guix i18n) #:use-module (gnu services) @@ -32,6 +33,8 @@ #:autoload (gnu packages base) (glibc-utf8-locales) #:use-module (gnu packages ssh) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-9) + #:use-module (srfi srfi-9 gnu) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:use-module (ice-9 match) @@ -55,6 +58,12 @@ openssh-host-host-key-algorithms openssh-host-accepted-key-types openssh-host-extra-content + proxy-jump + proxy-jump-host-name + proxy-jump-port + proxy-jump-user + proxy-command + proxy-command->string home-openssh-service-type home-ssh-agent-service-type)) @@ -114,6 +123,54 @@ (define-maybe string-list) +(define-record-type + (proxy-command command) + proxy-command? + (command proxy-command->string)) + +(set-record-type-printer! + (lambda (obj port) + (format port "#" (proxy-command->string obj)))) + +(define-configuration/no-serialization proxy-jump + (user + maybe-string + "User name on the remote host.") + (host-name + (string) + "Host name---e.g., @code{foo.example.org} or @code{192.168.1.2}.") + (port + maybe-natural-number + "TCP port number to connect to.")) + +(define (proxy-jump->string proxy-jump) + (match-record proxy-jump + (host-name user port) + (string-append + (if (maybe-value-set? user) (string-append user "@") "") + host-name + (if (maybe-value-set? port) (string-append ":" (number->string port)) "")))) + +(define (proxy-command-or-jump-list? x) + (or (proxy-command? x) + (and (list? x) + (every proxy-jump? x)))) + +(define (serialize-proxy-command-or-jump-list field value) + (if (proxy-command? value) + (serialize-string 'proxy-command (proxy-command->string value)) + (serialize-string-list 'proxy-jump (map proxy-jump->string value)))) + +(define-maybe proxy-command-or-jump-list) + +(define (sanitize-proxy-command properties) + (lambda (value) + (when (maybe-value-set? value) + (warn-about-deprecation 'proxy-command properties #:replacement 'proxy)) + (unless (maybe-string? value) + (configuration-field-error (source-properties->location properties) 'proxy-command value)) + value)) + (define-configuration openssh-host (name (string) @@ -155,7 +212,13 @@ machine.") maybe-string "The command to use to connect to the server. As an example, a command to connect via an HTTP proxy at 192.0.2.0 would be: @code{\"nc -X -connect -x 192.0.2.0:8080 %h %p\"}.") +connect -x 192.0.2.0:8080 %h %p\"}. Using 'proxy-command' is deprecated, use +'proxy' instead." + (sanitizer (sanitize-proxy-command (current-source-location)))) + (proxy + maybe-proxy-command-or-jump-list + "The command to use to connect to the server or a list of SSH hosts to jump +through before connecting to the server.") (host-key-algorithms maybe-string-list "The list of accepted host key algorithms---e.g., -- cgit v1.2.3