mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2025-01-12 14:16:55 -05:00
archive: Add '--authorize'.
* guix/scripts/archive.scm (authorize-key): New procedure. (guix-archive): Call it when OPTS contains 'authorize-key'. * tests/guix-archive.sh: Add test with invalid public key. * guix/pki.scm: Export '%acl-file'. * doc/guix.texi (Invoking guix archive): Make it clear that '--import' works only with authorized keys. Document '--authorize'.
This commit is contained in:
parent
554f26ece3
commit
f82cc5fdbe
4 changed files with 50 additions and 2 deletions
|
@ -942,7 +942,8 @@ Archives are stored in the ``Nix archive'' or ``Nar'' format, which is
|
||||||
comparable in spirit to `tar'. When exporting, the daemon digitally
|
comparable in spirit to `tar'. When exporting, the daemon digitally
|
||||||
signs the contents of the archive, and that digital signature is
|
signs the contents of the archive, and that digital signature is
|
||||||
appended. When importing, the daemon verifies the signature and rejects
|
appended. When importing, the daemon verifies the signature and rejects
|
||||||
the import in case of an invalid signature.
|
the import in case of an invalid signature or if the signing key is not
|
||||||
|
authorized.
|
||||||
@c FIXME: Add xref to daemon doc about signatures.
|
@c FIXME: Add xref to daemon doc about signatures.
|
||||||
|
|
||||||
The main options are:
|
The main options are:
|
||||||
|
@ -955,9 +956,11 @@ resulting archive to the standard output.
|
||||||
@item --import
|
@item --import
|
||||||
Read an archive from the standard input, and import the files listed
|
Read an archive from the standard input, and import the files listed
|
||||||
therein into the store. Abort if the archive has an invalid digital
|
therein into the store. Abort if the archive has an invalid digital
|
||||||
signature.
|
signature, or if it is signed by a public key not among the authorized
|
||||||
|
keys (see @code{--authorize} below.)
|
||||||
|
|
||||||
@item --generate-key[=@var{parameters}]
|
@item --generate-key[=@var{parameters}]
|
||||||
|
@cindex signing, archives
|
||||||
Generate a new key pair for the daemons. This is a prerequisite before
|
Generate a new key pair for the daemons. This is a prerequisite before
|
||||||
archives can be exported with @code{--export}. Note that this operation
|
archives can be exported with @code{--export}. Note that this operation
|
||||||
usually takes time, because it needs to gather enough entropy to
|
usually takes time, because it needs to gather enough entropy to
|
||||||
|
@ -970,6 +973,19 @@ is a 4096-bit RSA key. Alternately, @var{parameters} can specify
|
||||||
@code{genkey} parameters suitable for Libgcrypt (@pxref{General
|
@code{genkey} parameters suitable for Libgcrypt (@pxref{General
|
||||||
public-key related Functions, @code{gcry_pk_genkey},, gcrypt, The
|
public-key related Functions, @code{gcry_pk_genkey},, gcrypt, The
|
||||||
Libgcrypt Reference Manual}).
|
Libgcrypt Reference Manual}).
|
||||||
|
|
||||||
|
@item --authorize
|
||||||
|
@cindex authorizing, archives
|
||||||
|
Authorize imports signed by the public key passed on standard input.
|
||||||
|
The public key must be in ``s-expression advanced format''---i.e., the
|
||||||
|
same format as the @file{signing-key.pub} file.
|
||||||
|
|
||||||
|
The list of authorized keys is kept in the human-editable file
|
||||||
|
@file{/etc/guix/acl}. The file contains
|
||||||
|
@url{http://people.csail.mit.edu/rivest/Sexp.txt, ``advanced-format
|
||||||
|
s-expressions''} and is structured as an access-control list in the
|
||||||
|
@url{http://theworld.com/~cme/spki.txt, Simple Public-Key Infrastructure
|
||||||
|
(SPKI)}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
To export store files as an archive to the standard output, run:
|
To export store files as an archive to the standard output, run:
|
||||||
|
|
|
@ -24,6 +24,7 @@ (define-module (guix pki)
|
||||||
#:use-module (rnrs io ports)
|
#:use-module (rnrs io ports)
|
||||||
#:export (%public-key-file
|
#:export (%public-key-file
|
||||||
%private-key-file
|
%private-key-file
|
||||||
|
%acl-file
|
||||||
current-acl
|
current-acl
|
||||||
public-keys->acl
|
public-keys->acl
|
||||||
acl->public-keys
|
acl->public-keys
|
||||||
|
|
|
@ -32,6 +32,7 @@ (define-module (guix scripts archive)
|
||||||
#:use-module (srfi srfi-37)
|
#:use-module (srfi srfi-37)
|
||||||
#:use-module (guix scripts build)
|
#:use-module (guix scripts build)
|
||||||
#:use-module (guix scripts package)
|
#:use-module (guix scripts package)
|
||||||
|
#:use-module (rnrs io ports)
|
||||||
#:export (guix-archive))
|
#:export (guix-archive))
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +112,9 @@ (define %options
|
||||||
(lambda args
|
(lambda args
|
||||||
(leave (_ "invalid key generation parameters: ~s~%")
|
(leave (_ "invalid key generation parameters: ~s~%")
|
||||||
arg)))))
|
arg)))))
|
||||||
|
(option '("authorize") #f #f
|
||||||
|
(lambda (opt name arg result)
|
||||||
|
(alist-cons 'authorize #t result)))
|
||||||
|
|
||||||
(option '(#\S "source") #f #f
|
(option '(#\S "source") #f #f
|
||||||
(lambda (opt name arg result)
|
(lambda (opt name arg result)
|
||||||
|
@ -256,6 +260,28 @@ (define (generate-key-pair parameters)
|
||||||
;; Make the public key readable by everyone.
|
;; Make the public key readable by everyone.
|
||||||
(chmod %public-key-file #o444)))
|
(chmod %public-key-file #o444)))
|
||||||
|
|
||||||
|
(define (authorize-key)
|
||||||
|
"Authorize imports signed by the public key passed as an advanced sexp on
|
||||||
|
the input port."
|
||||||
|
(define (read-key)
|
||||||
|
(catch 'gcry-error
|
||||||
|
(lambda ()
|
||||||
|
(string->canonical-sexp (get-string-all (current-input-port))))
|
||||||
|
(lambda (key err)
|
||||||
|
(leave (_ "failed to read public key: ~a: ~a~%")
|
||||||
|
(error-source err) (error-string err)))))
|
||||||
|
|
||||||
|
(let ((key (read-key))
|
||||||
|
(acl (current-acl)))
|
||||||
|
(unless (eq? 'public-key (canonical-sexp-nth-data key 0))
|
||||||
|
(leave (_ "s-expression does not denote a public key~%")))
|
||||||
|
|
||||||
|
;; Add KEY to the ACL and write that.
|
||||||
|
(let ((acl (public-keys->acl (cons key (acl->public-keys acl)))))
|
||||||
|
(with-atomic-file-output %acl-file
|
||||||
|
(lambda (port)
|
||||||
|
(display (canonical-sexp->string acl) port))))))
|
||||||
|
|
||||||
(define (guix-archive . args)
|
(define (guix-archive . args)
|
||||||
(define (parse-options)
|
(define (parse-options)
|
||||||
;; Return the alist of option values.
|
;; Return the alist of option values.
|
||||||
|
@ -274,6 +300,8 @@ (define (parse-options)
|
||||||
(cond ((assoc-ref opts 'generate-key)
|
(cond ((assoc-ref opts 'generate-key)
|
||||||
=>
|
=>
|
||||||
generate-key-pair)
|
generate-key-pair)
|
||||||
|
((assoc-ref opts 'authorize)
|
||||||
|
(authorize-key))
|
||||||
(else
|
(else
|
||||||
(let ((store (open-connection)))
|
(let ((store (open-connection)))
|
||||||
(cond ((assoc-ref opts 'export)
|
(cond ((assoc-ref opts 'export)
|
||||||
|
|
|
@ -43,3 +43,6 @@ guix archive --import < "$archive" 2>&1 | grep "import.*guile-bootstrap"
|
||||||
|
|
||||||
if guix archive something-that-does-not-exist
|
if guix archive something-that-does-not-exist
|
||||||
then false; else true; fi
|
then false; else true; fi
|
||||||
|
|
||||||
|
if echo foo | guix archive --authorize
|
||||||
|
then false; else true; fi
|
||||||
|
|
Loading…
Reference in a new issue