From 2c8e04f13670c8c7ad8c7195c305960dd1905363 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Fri, 9 Aug 2019 14:24:57 -0400 Subject: remote: Build derivations appropriate for the remote's * gnu/machine/ssh.scm (machine-ssh-configuration): Add 'system' field. (managed-host-remote-eval): Pass 'system' field to 'remote-eval'. (machine-check-building-for-appropriate-system): New variable. (check-deployment-sanity): Add call to 'machine-check-building-for-appropriate-system'. * doc/guix.texi (Invoking guix deploy): Describe new 'system' field. * guix/ssh.scm (remote-system): New variable. * guix/remote.scm (remote-eval): Use result of 'remote-system' when lowering the G-Expression. (remote-eval): Add 'system' keyword argument. (trampoline): Return a rather than a . --- gnu/machine/ssh.scm | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index ba3e33c922..670990a633 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -36,6 +36,7 @@ #:use-module (ice-9 match) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) + #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:export (managed-host-environment-type @@ -68,6 +69,7 @@ machine-ssh-configuration? this-machine-ssh-configuration (host-name machine-ssh-configuration-host-name) ; string + (system machine-ssh-configuration-system) ; string (build-locally? machine-ssh-configuration-build-locally? (default #t)) (port machine-ssh-configuration-port ; integer @@ -103,10 +105,12 @@ one from the configuration's parameters if one was not provided." "Internal implementation of 'machine-remote-eval' for MACHINE instances with an environment type of 'managed-host." (maybe-raise-unsupported-configuration-error machine) - (remote-eval exp (machine-ssh-session machine) - #:build-locally? - (machine-ssh-configuration-build-locally? - (machine-configuration machine)))) + (let ((config (machine-configuration machine))) + (remote-eval exp (machine-ssh-session machine) + #:build-locally? + (machine-ssh-configuration-build-locally? config) + #:system + (machine-ssh-configuration-system config)))) ;;; @@ -240,10 +244,29 @@ MACHINE's 'system' declaration do not exist on the machine." device) (return #t))) +(define (machine-check-building-for-appropriate-system machine) + "Raise a '&message' error condition if MACHINE is configured to be built +locally and the 'system' field does not match the '%current-system' reported +by MACHINE." + (let ((config (machine-configuration machine)) + (system (remote-system (machine-ssh-session machine)))) + (when (and (machine-ssh-configuration-build-locally? config) + (not (string= system (machine-ssh-configuration-system config)))) + (raise (condition + (&message + (message (format #f (G_ "incorrect target system \ +('~a' was given, while the system reports that it is '~a')~%") + (machine-ssh-configuration-system config) + system))))))) + (with-monad %store-monad (return #t))) + (define (check-deployment-sanity machine) "Raise a '&message' error condition if it is clear that deploying MACHINE's 'system' declaration would fail." + ;; Order is important here -- an incorrect value for 'system' will cause + ;; invocations of 'remote-eval' to fail. (mbegin %store-monad + (machine-check-building-for-appropriate-system machine) (machine-check-file-system-availability machine) (machine-check-initrd-modules machine))) -- cgit v1.2.3 From 5ea7537b9a650cfa525401c19879080a9cf42e13 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 15 Aug 2019 04:05:04 -0400 Subject: machine: Allow non-root users to deploy. * doc/guix.texi (Invoking guix deploy): Add section describing prerequisites for deploying as a non-root user. * guix/remote.scm (remote-pipe-for-gexp): New optional 'become-command' argument. (%remote-eval): New optional 'become-command' argument. (remote-eval): New 'become-command' keyword argument. * guix/ssh.scm (remote-inferior): New optional 'become-command' argument. (inferior-remote-eval): New optional 'become-command' argument. (remote-authorize-signing-key): New optional 'become-command' argument. * gnu/machine/ssh.scm (machine-become-command): New variable. (managed-host-remote-eval): Invoke 'remote-eval' with the '#:become-command' keyword. (deploy-managed-host): Invoke 'remote-authorize-signing-key' with the '#:become-command' keyword. --- gnu/machine/ssh.scm | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index 670990a633..fb15d39e61 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -101,6 +101,14 @@ one from the configuration's parameters if one was not provided." ;;; Remote evaluation. ;;; +(define (machine-become-command machine) + "Return as a list of strings the program and arguments necessary to run a +shell command with escalated privileges for MACHINE's configuration." + (if (string= "root" (machine-ssh-configuration-user + (machine-configuration machine))) + '() + '("/run/setuid-programs/sudo" "-n" "--"))) + (define (managed-host-remote-eval machine exp) "Internal implementation of 'machine-remote-eval' for MACHINE instances with an environment type of 'managed-host." -- cgit v1.2.3 From 9c70c460a05b2bc60f3f3602f0a2dba0f79ce86c Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 15 Aug 2019 04:05:57 -0400 Subject: machine: Implement 'roll-back-machine'. * gnu/machine.scm (roll-back-machine, &deploy-error, deploy-error?) (deploy-error-should-roll-back) (deploy-error-captured-args): New variable. * gnu/machine/ssh.scm (roll-back-managed-host): New variable. * guix/scripts/deploy.scm (guix-deploy): Roll-back systems when a deployment fails. --- gnu/machine/ssh.scm | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index fb15d39e61..4b5d5fe3a2 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -17,6 +17,7 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu machine ssh) + #:use-module (gnu bootloader) #:use-module (gnu machine) #:autoload (gnu packages gnupg) (guile-gcrypt) #:use-module (gnu system) @@ -34,6 +35,7 @@ #:use-module (guix store) #:use-module (guix utils) #:use-module (ice-9 match) + #:use-module (srfi srfi-1) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) @@ -341,6 +343,18 @@ of MACHINE's system profile, ordered from most recent to oldest." (boot-parameters-kernel-arguments params)))))))) generations)))) +(define-syntax-rule (with-roll-back should-roll-back? mbody ...) + "Catch exceptions that arise when binding MBODY, a monadic expression in +%STORE-MONAD, and collect their arguments in a &deploy-error condition, with +the 'should-roll-back' field set to SHOULD-ROLL-BACK?" + (catch #t + (lambda () + mbody ...) + (lambda args + (raise (condition (&deploy-error + (should-roll-back should-roll-back?) + (captured-args args))))))) + (define (deploy-managed-host machine) "Internal implementation of 'deploy-machine' for MACHINE instances with an environment type of 'managed-host." @@ -353,9 +367,60 @@ environment type of 'managed-host." (bootloader-configuration (operating-system-bootloader os)) (bootcfg (operating-system-bootcfg os menu-entries))) (mbegin %store-monad - (switch-to-system eval os) - (upgrade-shepherd-services eval os) - (install-bootloader eval bootloader-configuration bootcfg))))) + (with-roll-back #f + (switch-to-system eval os)) + (with-roll-back #t + (mbegin %store-monad + (upgrade-shepherd-services eval os) + (install-bootloader eval bootloader-configuration bootcfg))))))) + + +;;; +;;; Roll-back. +;;; + +(define (roll-back-managed-host machine) + "Internal implementation of 'roll-back-machine' for MACHINE instances with +an environment type of 'managed-host." + (define remote-exp + (with-extensions (list guile-gcrypt) + (with-imported-modules (source-module-closure '((guix config) + (guix profiles))) + #~(begin + (use-modules (guix config) + (guix profiles)) + + (define %system-profile + (string-append %state-directory "/profiles/system")) + + (define target-generation + (relative-generation %system-profile -1)) + + (if target-generation + (switch-to-generation %system-profile target-generation) + 'error))))) + + (define roll-back-failure + (condition (&message (message (G_ "could not roll-back machine"))))) + + (mlet* %store-monad ((boot-parameters (machine-boot-parameters machine)) + (_ -> (if (< (length boot-parameters) 2) + (raise roll-back-failure))) + (entries -> (map boot-parameters->menu-entry + (list (second boot-parameters)))) + (old-entries -> (map boot-parameters->menu-entry + (drop boot-parameters 2))) + (bootloader -> (operating-system-bootloader + (machine-operating-system machine))) + (bootcfg (lower-object + ((bootloader-configuration-file-generator + (bootloader-configuration-bootloader + bootloader)) + bootloader entries + #:old-entries old-entries))) + (remote-result (machine-remote-eval machine remote-exp))) + (when (eqv? 'error remote-result) + (raise roll-back-failure)))) ;;; @@ -366,6 +431,7 @@ environment type of 'managed-host." (environment-type (machine-remote-eval managed-host-remote-eval) (deploy-machine deploy-managed-host) + (roll-back-machine roll-back-managed-host) (name 'managed-host-environment-type) (description "Provisioning for machines that are accessible over SSH and have a known host-name. This entails little more than maintaining an SSH -- cgit v1.2.3 From 3033d59ac9a747b42a1fa6ca6664d4fbc62ca117 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 15 Aug 2019 04:06:41 -0400 Subject: machine: Automatically authorize the coordinator's signing key. * guix/ssh.scm (remote-authorize-signing-key): New variable. * gnu/machine/ssh.scm (deploy-managed-host): Authorize coordinator's signing key before any invocations of 'remote-eval'. (deploy-managed-host): Display an error if a signing key does not exist. * doc/guix.texi (Invoking guix deploy): Remove section describing manual signing key authorization. (Invoking guix deploy): Add section describing the 'authorize?' field. --- gnu/machine/ssh.scm | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index 4b5d5fe3a2..ac3aa3e370 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -28,13 +28,16 @@ #:use-module (guix i18n) #:use-module (guix modules) #:use-module (guix monads) + #:use-module (guix pki) #:use-module (guix records) #:use-module (guix remote) #:use-module (guix scripts system reconfigure) #:use-module (guix ssh) #:use-module (guix store) #:use-module (guix utils) + #:use-module (gcrypt pk-crypto) #:use-module (ice-9 match) + #:use-module (ice-9 textual-ports) #:use-module (srfi srfi-1) #:use-module (srfi srfi-19) #:use-module (srfi srfi-26) @@ -48,6 +51,7 @@ machine-ssh-configuration-host-name machine-ssh-configuration-build-locally? + machine-ssh-configuration-authorize? machine-ssh-configuration-port machine-ssh-configuration-user machine-ssh-configuration-session)) @@ -70,17 +74,19 @@ make-machine-ssh-configuration machine-ssh-configuration? this-machine-ssh-configuration - (host-name machine-ssh-configuration-host-name) ; string - (system machine-ssh-configuration-system) ; string - (build-locally? machine-ssh-configuration-build-locally? + (host-name machine-ssh-configuration-host-name) ; string + (system machine-ssh-configuration-system) ; string + (build-locally? machine-ssh-configuration-build-locally? ; boolean (default #t)) - (port machine-ssh-configuration-port ; integer + (authorize? machine-ssh-configuration-authorize? ; boolean + (default #t)) + (port machine-ssh-configuration-port ; integer (default 22)) - (user machine-ssh-configuration-user ; string + (user machine-ssh-configuration-user ; string (default "root")) - (identity machine-ssh-configuration-identity ; path to a private key + (identity machine-ssh-configuration-identity ; path to a private key (default #f)) - (session machine-ssh-configuration-session ; session + (session machine-ssh-configuration-session ; session (default #f))) (define (machine-ssh-session machine) @@ -359,6 +365,19 @@ the 'should-roll-back' field set to SHOULD-ROLL-BACK?" "Internal implementation of 'deploy-machine' for MACHINE instances with an environment type of 'managed-host." (maybe-raise-unsupported-configuration-error machine) + (when (machine-ssh-configuration-authorize? + (machine-configuration machine)) + (unless (file-exists? %public-key-file) + (raise (condition + (&message + (message (format #f (G_ "no signing key '~a'. \ +have you run 'guix archive --generate-key?'") + %public-key-file)))))) + (remote-authorize-signing-key (call-with-input-file %public-key-file + (lambda (port) + (string->canonical-sexp + (get-string-all port)))) + (machine-ssh-session machine))) (mlet %store-monad ((_ (check-deployment-sanity machine)) (boot-parameters (machine-boot-parameters machine))) (let* ((os (machine-operating-system machine)) -- cgit v1.2.3 From 4cc5e5204b503afb4536a1e93e2fd7a9f57f12bf Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Thu, 15 Aug 2019 12:09:11 -0400 Subject: machine: Use 'become-command'. * gnu/machine/ssh.scm (managed-host-remote-eval): Pass an appropriate 'become-command' to 'remote-eval'. * guix/ssh.scm (remote-authorize-signing-key): Add optional 'become-command' argument. All callers changed. --- gnu/machine/ssh.scm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index ac3aa3e370..aafe0ccf41 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -126,7 +126,9 @@ an environment type of 'managed-host." #:build-locally? (machine-ssh-configuration-build-locally? config) #:system - (machine-ssh-configuration-system config)))) + (machine-ssh-configuration-system config) + #:become-command + (machine-become-command machine)))) ;;; @@ -377,7 +379,8 @@ have you run 'guix archive --generate-key?'") (lambda (port) (string->canonical-sexp (get-string-all port)))) - (machine-ssh-session machine))) + (machine-ssh-session machine) + (machine-become-command machine))) (mlet %store-monad ((_ (check-deployment-sanity machine)) (boot-parameters (machine-boot-parameters machine))) (let* ((os (machine-operating-system machine)) -- cgit v1.2.3 From 02460db0474ff5ac0d867ed6d5b192c062af0abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E6=96=87=E6=AD=A6?= Date: Sat, 17 Aug 2019 20:26:58 +0800 Subject: machine: ssh: Fix sanity checks. * gnu/machine/ssh.scm (machine-check-file-system-availability)[check-labeled-file-system]: Use 'source-module-closure' for '(gnu build file-systems)'. (machine-check-initrd-modules): Unquote 'file-system-label->string' instead of 'device'. --- gnu/machine/ssh.scm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gnu/machine/ssh.scm') diff --git a/gnu/machine/ssh.scm b/gnu/machine/ssh.scm index aafe0ccf41..6e3ed0e092 100644 --- a/gnu/machine/ssh.scm +++ b/gnu/machine/ssh.scm @@ -166,7 +166,8 @@ MACHINE's 'system' declaration do not exist on the machine." (define (check-labeled-file-system fs) (define remote-exp - (with-imported-modules '((gnu build file-systems)) + (with-imported-modules (source-module-closure + '((gnu build file-systems))) #~(begin (use-modules (gnu build file-systems)) (find-partition-by-label #$(file-system-label->string @@ -243,7 +244,7 @@ MACHINE's 'system' declaration do not exist on the machine." #$(uuid->string device)))) ((file-system-label? device) #~(find-partition-by-label - (file-system-label->string #$device))))) + #$(file-system-label->string device))))) (missing-modules dev '#$(operating-system-initrd-modules (machine-operating-system machine))))))) -- cgit v1.2.3